├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── pom.xml ├── sofa-dashboard-backend ├── pom.xml ├── sofa-dashboard-application │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── alipay │ │ │ └── sofa │ │ │ └── dashboard │ │ │ └── app │ │ │ ├── AppServiceImpl.java │ │ │ └── MonitorServiceImpl.java │ │ └── test │ │ └── java │ │ └── com │ │ └── alipay │ │ └── sofa │ │ └── dashboard │ │ ├── app │ │ ├── AppServiceTest.java │ │ └── MonitorServiceTest.java │ │ └── mock │ │ ├── MockRegistry.java │ │ └── MockStore.java ├── sofa-dashboard-arkmng │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── alipay │ │ └── sofa │ │ └── dashboard │ │ ├── dao │ │ └── ArkDao.java │ │ ├── impl │ │ ├── ArkMngServiceImpl.java │ │ ├── ZkCommandPushManager.java │ │ └── ZkHelper.java │ │ ├── model │ │ ├── AppArkDO.java │ │ ├── AppArkModel.java │ │ ├── AppModuleModel.java │ │ ├── AppUnitModel.java │ │ ├── ArkAppModel.java │ │ ├── ArkModuleUserDO.java │ │ ├── ArkModuleVersionDO.java │ │ ├── ArkPluginDO.java │ │ ├── ArkPluginModel.java │ │ ├── BizModel.java │ │ └── ClientResponseModel.java │ │ └── service │ │ └── ArkMngService.java ├── sofa-dashboard-core │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── alipay │ │ └── sofa │ │ └── dashboard │ │ ├── callback │ │ └── BizStateCallable.java │ │ ├── constants │ │ ├── SofaDashboardConstants.java │ │ └── enums │ │ │ └── ResponseCode.java │ │ ├── model │ │ ├── AppModel.java │ │ ├── ApplicationInfo.java │ │ ├── CommandRequest.java │ │ ├── ServiceAppModel.java │ │ ├── ServiceModel.java │ │ └── StampedValueEntity.java │ │ ├── spi │ │ ├── AppService.java │ │ ├── ApplicationManager.java │ │ ├── CommandPushManager.java │ │ └── MonitorService.java │ │ ├── utils │ │ ├── FastJsonUtils.java │ │ ├── ObjectBytesUtil.java │ │ └── SofaDashboardUtil.java │ │ └── zookeeper │ │ └── ZkCommandClient.java ├── sofa-dashboard-governance │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── alipay │ │ └── sofa │ │ └── dashboard │ │ ├── cache │ │ ├── RegistryDataCache.java │ │ ├── SofaRegistryDataCacheImpl.java │ │ └── ZookeeperRegistryDataCacheImpl.java │ │ ├── configuration │ │ └── GovernanceConfiguration.java │ │ ├── domain │ │ ├── RpcConsumer.java │ │ ├── RpcProvider.java │ │ └── RpcService.java │ │ ├── listener │ │ ├── ApplicationStartedListener.java │ │ ├── RegistryDataChangeListener.java │ │ ├── sofa │ │ │ └── SofaRegistryRestClient.java │ │ └── zookeeper │ │ │ ├── ConsumerNodeChangeListener.java │ │ │ ├── ProviderNodeChangeListener.java │ │ │ ├── RootNodeChangeListener.java │ │ │ └── ServiceNodeChangeListener.java │ │ ├── registry │ │ ├── AdminRegistry.java │ │ ├── SofaAdminRegistry.java │ │ └── ZookeeperAdminRegistry.java │ │ └── sync │ │ ├── RegistryDataSync.java │ │ ├── RegistryDataSyncManager.java │ │ ├── RegistryDataSyncManagerImpl.java │ │ ├── SofaRegistryDataSync.java │ │ └── ZookeeperRegistryDataSync.java └── sofa-dashboard-web │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── alipay │ │ │ └── sofa │ │ │ └── dashboard │ │ │ ├── SofaAdminServerApplication.java │ │ │ ├── configuration │ │ │ └── CorsConfiguration.java │ │ │ ├── controller │ │ │ ├── ApplicationController.java │ │ │ ├── ArkAppMngController.java │ │ │ ├── ArkMngController.java │ │ │ ├── InstanceController.java │ │ │ └── ServiceManageController.java │ │ │ ├── model │ │ │ ├── InstanceRecord.java │ │ │ ├── RecordResponse.java │ │ │ └── TreeNode.java │ │ │ ├── response │ │ │ └── ResponseEntity.java │ │ │ └── utils │ │ │ ├── HostPortUtils.java │ │ │ ├── MapUtils.java │ │ │ └── TreeNodeConverter.java │ └── resources │ │ ├── application-localhost.properties │ │ ├── application.properties │ │ ├── logback-spring.xml │ │ └── spring │ │ ├── mybatis-configuration.xml │ │ └── mybatis │ │ └── ArkMapper.xml │ └── test │ ├── java │ └── com │ │ └── alipay │ │ └── sofa │ │ └── dashboard │ │ ├── ArkManagementTest.java │ │ ├── ArkMngServiceTest.java │ │ ├── ServiceManageControllerTest.java │ │ ├── SofaAdminRegistryTest.java │ │ ├── ZkCommandPushManagerTest.java │ │ ├── ZkHelperTest.java │ │ ├── base │ │ └── AbstractTestBase.java │ │ └── utils │ │ ├── FastJsonUtilsTest.java │ │ └── SofaDashboardUtilTest.java │ └── resources │ ├── SofaDashboardDB.sql │ ├── application-test-sofa.properties │ └── application-test.properties ├── sofa-dashboard-front ├── .eslintrc.js ├── README.md ├── config │ ├── config.js │ └── routes.config.js ├── jsconfig.json ├── mock │ └── user.js ├── package.json ├── pom.xml └── src │ ├── layouts │ └── BasicLayout.jsx │ ├── models │ ├── application.js │ ├── ark.js │ ├── arkapp.js │ ├── governance.js │ ├── instance.js │ ├── monitor.js │ └── user.js │ ├── pages │ ├── Ark │ │ ├── RegisterPluginFrom.jsx │ │ ├── RegisterVersionForm.jsx │ │ ├── RelatedAppForm.jsx │ │ ├── arkapp.jsx │ │ └── index.jsx │ ├── DemoPage │ │ └── index.jsx │ ├── Governance │ │ ├── details.jsx │ │ └── index.jsx │ ├── Instance │ │ ├── actuator.jsx │ │ ├── component │ │ │ ├── MetricsGraph.jsx │ │ │ ├── PropertyDetail.jsx │ │ │ └── PropsMonitor.jsx │ │ ├── index.jsx │ │ ├── monitor.jsx │ │ ├── monitor.less │ │ └── tab │ │ │ ├── environment.jsx │ │ │ ├── loggers.jsx │ │ │ ├── mappings.jsx │ │ │ └── overview.jsx │ ├── Login │ │ ├── index.jsx │ │ └── index.less │ └── Overview │ │ └── index.jsx │ ├── services │ ├── application.js │ ├── ark.js │ ├── arkapp.js │ ├── governance.js │ └── user.js │ └── utils │ └── request.js ├── sql └── SofaDashboardDB.sql └── tools ├── change_version.sh ├── check_format.sh └── codestyle ├── HEADER └── formatter.xml /.gitignore: -------------------------------------------------------------------------------- 1 | /target/* 2 | target 3 | bak 4 | .pmd 5 | .project 6 | .settings 7 | .classpath 8 | .idea.xml 9 | .idea 10 | *.class 11 | *.bak 12 | *.iml 13 | *.ipr 14 | *.iws 15 | null/ 16 | tree.log 17 | tmp/ 18 | *.log 19 | *.DS_Store 20 | logs/ 21 | node_modules 22 | **/node_modules 23 | .vscode 24 | application-alipay.properties 25 | coverage-report 26 | /src/utils/request-temp.js 27 | _roadhog-api-doc 28 | /dist 29 | npm-debug.log* 30 | yarn-error.log 31 | /coverage 32 | yarn.lock 33 | package-lock.json 34 | .history 35 | functions/mock 36 | .temp 37 | .umi 38 | .umi-production 39 | screenshot 40 | .firebase 41 | application-localhost.properties -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | 4 | jdk: 5 | - openjdk8 6 | 7 | install: 8 | - mvn clean install -DskipTests -B -V 9 | - mvn test 10 | 11 | script: 12 | - sh ./tools/check_format.sh 13 | 14 | after_success: 15 | - bash <(curl -s https://codecov.io/bash) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## SOFADashboard 2 | 3 | [![Build Status](https://travis-ci.com/sofastack/sofa-dashboard.svg?branch=master)](https://travis-ci.com/sofastack/sofa-dashboard) 4 | [![Coverage Status](https://codecov.io/gh/sofastack/sofa-dashboard/branch/master/graph/badge.svg)](https://codecov.io/gh/sofastack/sofa-dashboard) 5 | ![license](https://img.shields.io/badge/license-Apache--2.0-green.svg) 6 | 7 | SOFADashboard 致力于对 SOFA 框架中组件进行统一管理,包括服务治理、SOFAArk 管控等。SOFADashboard 本身所用技术栈均基于开源社区产品来开发构建,包括:Ant Design Pro、SOFABoot、Spring、MyBatis 等 8 | 9 | ## 功能特性 10 | 11 | - 应用面板功能,用于查看应用信息 12 | - 基于 Zookeeper 的服务治理功能 13 | - [SOFAArk](https://github.com/sofastack/sofa-ark)多模块管理功能 14 | 15 | ## 运行依赖 16 | 17 | 编译需要 JDK 8 及以上、Maven 3.2.5 及以上,运行需要 JDK 8 及以上。 18 | 19 | SOFAArk 管控需要依赖 MySQL 进行资源数据存储,需要安装 MySQL 并导入 SofaDashboardDB.sql 脚本。 20 | 21 | SOFADashboard 中的服务治理、SOFAArk 管控依赖于 Zookeeper,需要启动 Zookeeper 服务。 22 | 23 | ## 文档 24 | 25 | - [快速开始](https://www.sofastack.tech/sofa-dashboard/docs/QuickStart) 26 | - [发布历史](https://www.sofastack.tech/sofa-dashboard/docs/ReleaseNode)  27 | - [发展路线](https://www.sofastack.tech/sofa-dashboard/docs/RoadMap)  28 | 29 | ## 如何贡献 30 | 31 | [如何参与 SOFADashboard 代码贡献](https://www.sofastack.tech/sofa-dashboard/docs/Contribution)  32 | 33 | ## 开源许可 34 | 35 | SOFADashboard 基于 Apache License 2.0 协议,SOFADashboard 依赖了一些三方组件,它们的开源协议参见[依赖组件版权说明](https://www.sofastack.tech/sofa-dashboard/docs/Notice)。 36 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | pom 7 | 8 | sofa-dashboard-front 9 | sofa-dashboard-backend 10 | 11 | 12 | com.alipay.sofa 13 | sofaboot-dependencies 14 | 3.10.0 15 | 16 | 17 | sofa-dashboard 18 | 1.0.0-SNAPSHOT 19 | sofa-dashboard 20 | SOFADashboard 21 | 22 | 23 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-application/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofa-dashboard-backend 7 | com.alipay.sofa 8 | 1.0.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | sofa-dashboard-application 14 | 15 | 16 | ../../ 17 | 18 | 19 | 20 | 21 | com.alipay.sofa 22 | sofa-dashboard-core 23 | 24 | 25 | com.alipay.sofa 26 | dashboard-support 27 | 28 | 29 | 30 | 31 | junit 32 | junit 33 | 34 | 35 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-application/src/main/java/com/alipay/sofa/dashboard/app/AppServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.app; 18 | 19 | import com.alipay.sofa.dashboard.client.model.common.Application; 20 | import com.alipay.sofa.dashboard.client.registry.AppSubscriber; 21 | import com.alipay.sofa.dashboard.model.ApplicationInfo; 22 | import com.alipay.sofa.dashboard.spi.AppService; 23 | import org.springframework.lang.Nullable; 24 | import org.springframework.stereotype.Service; 25 | import org.springframework.util.StringUtils; 26 | 27 | import java.util.List; 28 | import java.util.stream.Collectors; 29 | 30 | /** 31 | * 应用实例服务实现 32 | * 33 | * @author guolei.sgl (guolei.sgl@antfin.com) 2019/7/11 2:45 PM 34 | **/ 35 | @Service 36 | public class AppServiceImpl implements AppService { 37 | 38 | private final AppSubscriber subscriber; 39 | 40 | public AppServiceImpl(AppSubscriber subscriber) { 41 | this.subscriber = subscriber; 42 | } 43 | 44 | @Override 45 | public List getAllStatistics() { 46 | return getStatisticsByKeyword(null); 47 | } 48 | 49 | @Override 50 | public List getStatisticsByKeyword(@Nullable String keyword) { 51 | return subscriber.summaryCounts().entrySet().stream().map(entry -> { 52 | ApplicationInfo statistic = new ApplicationInfo(); 53 | statistic.setApplicationName(entry.getKey()); 54 | statistic.setApplicationCount(entry.getValue()); 55 | return statistic; 56 | }).filter(it -> 57 | // 关键词为空或者服务名包含关键词 58 | (StringUtils.isEmpty(keyword) || 59 | // 名字不为空,并且实例数不为 0 60 | !StringUtils.isEmpty(it.getApplicationName()) 61 | && it.getApplicationName().contains(keyword)) && it.getApplicationCount() > 0 62 | ).collect(Collectors.toList()); 63 | } 64 | 65 | @Override 66 | public List getAllInstances() { 67 | return subscriber.getAll(); 68 | } 69 | 70 | @Override 71 | public List getInstancesByName(@Nullable String serviceName) { 72 | return StringUtils.isEmpty(serviceName) ? subscriber.getAll() : subscriber 73 | .getByName(serviceName); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-application/src/test/java/com/alipay/sofa/dashboard/mock/MockStore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.mock; 18 | 19 | import com.alipay.sofa.dashboard.client.io.RecordExporter; 20 | import com.alipay.sofa.dashboard.client.io.RecordImporter; 21 | import com.alipay.sofa.dashboard.client.model.common.HostAndPort; 22 | import com.alipay.sofa.dashboard.client.model.io.StoreRecord; 23 | import org.junit.rules.TestRule; 24 | import org.junit.runner.Description; 25 | import org.junit.runners.model.Statement; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Comparator; 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | import java.util.Optional; 33 | import java.util.PriorityQueue; 34 | import java.util.Queue; 35 | import java.util.Set; 36 | import java.util.concurrent.ConcurrentHashMap; 37 | import java.util.concurrent.PriorityBlockingQueue; 38 | 39 | /** 40 | * 用于单元测试的存储实例 41 | */ 42 | public class MockStore implements TestRule, RecordImporter, RecordExporter { 43 | 44 | private final Map>> store = new ConcurrentHashMap<>(); 45 | 46 | @Override 47 | public Statement apply(Statement statement, Description description) { 48 | return new Statement() { 49 | @Override 50 | public void evaluate() throws Throwable { 51 | store.clear(); // 在测例执行前清空一次Store数据 52 | statement.evaluate(); 53 | } 54 | }; 55 | } 56 | 57 | @Override 58 | public List getLatestRecords(HostAndPort hostAndPort, String schemeName, 59 | long duration) { 60 | Queue records = store.getOrDefault(hostAndPort, new HashMap<>()).getOrDefault( 61 | schemeName, new PriorityQueue<>()); 62 | return new ArrayList<>(records); 63 | } 64 | 65 | @Override 66 | public void createTablesIfNotExists(HostAndPort hostAndPort, Set dimensionSchemes) { 67 | // Do nothing here 68 | } 69 | 70 | @Override 71 | public void addRecords(HostAndPort hostAndPort, List records) { 72 | store.compute(hostAndPort, (key, value) -> { 73 | Map> data = Optional.ofNullable(value) 74 | .orElse(new ConcurrentHashMap<>()); 75 | for (StoreRecord record : records) { 76 | data.compute(record.getSchemeName(), (dKey, dValue) -> { 77 | Queue queue = Optional.ofNullable(dValue) 78 | .orElse(new PriorityBlockingQueue<>(16, 79 | Comparator.comparingLong(o -> o.getTimestamp()))); 80 | queue.add(record); 81 | return queue; 82 | }); 83 | } 84 | return data; 85 | }); 86 | } 87 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofa-dashboard-backend 7 | com.alipay.sofa 8 | 1.0.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | sofa-dashboard-arkmng 14 | 15 | 16 | ../../ 17 | 18 | 19 | 20 | 21 | 22 | org.mybatis.spring.boot 23 | mybatis-spring-boot-starter 24 | 25 | 26 | mysql 27 | mysql-connector-java 28 | 29 | 30 | 31 | com.alibaba 32 | druid-spring-boot-starter 33 | 34 | 35 | 36 | com.alipay.sofa 37 | sofa-dashboard-core 38 | 39 | 40 | 41 | com.alipay.sofa 42 | sofa-ark-api 43 | 44 | 45 | 46 | com.alipay.sofa 47 | sofa-ark-spi 48 | 49 | 50 | com.alipay.sofa 51 | sofa-dashboard-application 52 | 1.0.0-SNAPSHOT 53 | compile 54 | 55 | 56 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/AppArkDO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * 应用-ark 关联关系 23 | * 24 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/18 下午5:51 25 | * @since: 26 | **/ 27 | public class AppArkDO { 28 | private Integer id; 29 | private Integer moduleId; 30 | private String appName; 31 | private Date createTime; 32 | 33 | public Integer getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Integer id) { 38 | this.id = id; 39 | } 40 | 41 | public Integer getModuleId() { 42 | return moduleId; 43 | } 44 | 45 | public void setModuleId(Integer moduleId) { 46 | this.moduleId = moduleId; 47 | } 48 | 49 | public String getAppName() { 50 | return appName; 51 | } 52 | 53 | public void setAppName(String appName) { 54 | this.appName = appName; 55 | } 56 | 57 | public Date getCreateTime() { 58 | return createTime; 59 | } 60 | 61 | public void setCreateTime(Date createTime) { 62 | this.createTime = createTime; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "AppArkDO{" + "id=" + id + ", moduleId=" + moduleId + ", appName='" + appName + '\'' 68 | + ", createTime=" + createTime + '}'; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/AppArkModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/18 下午5:52 21 | * @since: 22 | **/ 23 | public class AppArkModel { 24 | 25 | private String appName; 26 | private String createTime; 27 | private int instanceNum; 28 | 29 | public String getAppName() { 30 | return appName; 31 | } 32 | 33 | public void setAppName(String appName) { 34 | this.appName = appName; 35 | } 36 | 37 | public int getInstanceNum() { 38 | return instanceNum; 39 | } 40 | 41 | public void setInstanceNum(int instanceNum) { 42 | this.instanceNum = instanceNum; 43 | } 44 | 45 | public String getCreateTime() { 46 | return createTime; 47 | } 48 | 49 | public void setCreateTime(String createTime) { 50 | this.createTime = createTime; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/AppModuleModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | 22 | /** 23 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/24 上午11:12 24 | * @since: 25 | **/ 26 | public class AppModuleModel { 27 | /** 28 | * 默认版本 29 | */ 30 | private String defaultVersion; 31 | 32 | private String pluginName; 33 | private String appName; 34 | 35 | /** 36 | * 所有应用列表 37 | */ 38 | private List ipUnitList; 39 | 40 | /** 41 | * 版本列表 42 | */ 43 | private List versionList = new ArrayList<>(); 44 | 45 | public String getDefaultVersion() { 46 | return defaultVersion; 47 | } 48 | 49 | public void setDefaultVersion(String defaultVersion) { 50 | this.defaultVersion = defaultVersion; 51 | } 52 | 53 | public List getVersionList() { 54 | return versionList; 55 | } 56 | 57 | public void setVersionList(List versionList) { 58 | this.versionList = versionList; 59 | } 60 | 61 | public String getPluginName() { 62 | return pluginName; 63 | } 64 | 65 | public void setPluginName(String pluginName) { 66 | this.pluginName = pluginName; 67 | } 68 | 69 | public String getAppName() { 70 | return appName; 71 | } 72 | 73 | public void setAppName(String appName) { 74 | this.appName = appName; 75 | } 76 | 77 | public List getIpUnitList() { 78 | return ipUnitList; 79 | } 80 | 81 | public void setIpUnitList(List ipUnitList) { 82 | this.ipUnitList = ipUnitList; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/AppUnitModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/21 下午2:29 21 | * @since: 22 | **/ 23 | public class AppUnitModel { 24 | 25 | private String ip; 26 | private String status; 27 | private int port; 28 | 29 | public String getIp() { 30 | return ip; 31 | } 32 | 33 | public void setIp(String ip) { 34 | this.ip = ip; 35 | } 36 | 37 | public String getStatus() { 38 | return status; 39 | } 40 | 41 | public void setStatus(String status) { 42 | this.status = status; 43 | } 44 | 45 | public int getPort() { 46 | return port; 47 | } 48 | 49 | public void setPort(int port) { 50 | this.port = port; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ArkAppModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/19 上午11:04 23 | * @since: 24 | **/ 25 | public class ArkAppModel { 26 | private int appId; 27 | private String appName; 28 | private String pluginName; 29 | private String pluginVersion; 30 | private List ipUnitList; 31 | 32 | public int getAppId() { 33 | return appId; 34 | } 35 | 36 | public void setAppId(int appId) { 37 | this.appId = appId; 38 | } 39 | 40 | public String getAppName() { 41 | return appName; 42 | } 43 | 44 | public void setAppName(String appName) { 45 | this.appName = appName; 46 | } 47 | 48 | public String getPluginName() { 49 | return pluginName; 50 | } 51 | 52 | public void setPluginName(String pluginName) { 53 | this.pluginName = pluginName; 54 | } 55 | 56 | public String getPluginVersion() { 57 | return pluginVersion; 58 | } 59 | 60 | public void setPluginVersion(String pluginVersion) { 61 | this.pluginVersion = pluginVersion; 62 | } 63 | 64 | public List getIpUnitList() { 65 | return ipUnitList; 66 | } 67 | 68 | public void setIpUnitList(List ipUnitList) { 69 | this.ipUnitList = ipUnitList; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ArkModuleUserDO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/10 下午5:32 23 | * @since: 24 | **/ 25 | public class ArkModuleUserDO { 26 | private Integer id; 27 | private Integer moduleId; 28 | private Integer userId; 29 | private Date createTime; 30 | 31 | public Integer getId() { 32 | return id; 33 | } 34 | 35 | public void setId(Integer id) { 36 | this.id = id; 37 | } 38 | 39 | public Integer getModuleId() { 40 | return moduleId; 41 | } 42 | 43 | public void setModuleId(Integer moduleId) { 44 | this.moduleId = moduleId; 45 | } 46 | 47 | public Integer getUserId() { 48 | return userId; 49 | } 50 | 51 | public void setUserId(Integer userId) { 52 | this.userId = userId; 53 | } 54 | 55 | public Date getCreateTime() { 56 | return createTime; 57 | } 58 | 59 | public void setCreateTime(Date createTime) { 60 | this.createTime = createTime; 61 | } 62 | 63 | @Override 64 | public String toString() { 65 | return "ArkModuleUserDO{" + "id=" + id + ", moduleId=" + moduleId + ", userId=" + userId 66 | + ", createTime=" + createTime + '}'; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ArkModuleVersionDO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/10 下午5:22 23 | * @since: 24 | **/ 25 | public class ArkModuleVersionDO { 26 | 27 | private Integer id; 28 | private Integer moduleId; 29 | private String moduleVersion; 30 | private String sourcePath; 31 | private Date createTime; 32 | private Byte isRelease; 33 | 34 | public int getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Integer id) { 39 | this.id = id; 40 | } 41 | 42 | public Integer getModuleId() { 43 | return moduleId; 44 | } 45 | 46 | public void setModuleId(Integer moduleId) { 47 | this.moduleId = moduleId; 48 | } 49 | 50 | public String getModuleVersion() { 51 | return moduleVersion; 52 | } 53 | 54 | public void setModuleVersion(String moduleVersion) { 55 | this.moduleVersion = moduleVersion; 56 | } 57 | 58 | public String getSourcePath() { 59 | return sourcePath; 60 | } 61 | 62 | public void setSourcePath(String sourcePath) { 63 | this.sourcePath = sourcePath; 64 | } 65 | 66 | public Date getCreateTime() { 67 | return createTime; 68 | } 69 | 70 | public void setCreateTime(Date createTime) { 71 | this.createTime = createTime; 72 | } 73 | 74 | public Byte getIsRelease() { 75 | return isRelease; 76 | } 77 | 78 | public void setIsRelease(Byte isRelease) { 79 | this.isRelease = isRelease; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "ArkModuleVersionDO{" + "id=" + id + ", moduleId=" + moduleId + ", moduleVersion='" 85 | + moduleVersion + '\'' + ", sourcePath='" + sourcePath + '\'' + ", createTime=" 86 | + createTime + ", isRelease=" + isRelease + '}'; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ArkPluginDO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.Date; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/10 下午4:13 23 | * @since: 24 | **/ 25 | public class ArkPluginDO { 26 | private Integer id; 27 | private String pluginName; 28 | private Date createTime; 29 | private String description; 30 | 31 | public Integer getId() { 32 | return id; 33 | } 34 | 35 | public void setId(Integer id) { 36 | this.id = id; 37 | } 38 | 39 | public String getPluginName() { 40 | return pluginName; 41 | } 42 | 43 | public void setPluginName(String pluginName) { 44 | this.pluginName = pluginName; 45 | } 46 | 47 | public String getDescription() { 48 | return description; 49 | } 50 | 51 | public void setDescription(String description) { 52 | this.description = description; 53 | } 54 | 55 | public Date getCreateTime() { 56 | return createTime; 57 | } 58 | 59 | public void setCreateTime(Date createTime) { 60 | this.createTime = createTime; 61 | } 62 | 63 | public ArkPluginDO(String pluginName, Date createTime, String description) { 64 | this.pluginName = pluginName; 65 | this.createTime = createTime; 66 | this.description = description; 67 | } 68 | 69 | public ArkPluginDO() { 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "ArkPluginDO{" + "id=" + id + ", pluginName='" + pluginName + '\'' + ", createTime=" 75 | + createTime + ", description='" + description + '\'' + '}'; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ArkPluginModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/19 上午10:55 23 | * @since: 24 | **/ 25 | public class ArkPluginModel { 26 | private int id; 27 | private String pluginName; 28 | private List versions; 29 | private String address; 30 | private String description; 31 | private List appArkList; 32 | 33 | public int getId() { 34 | return id; 35 | } 36 | 37 | public void setId(int id) { 38 | this.id = id; 39 | } 40 | 41 | public String getPluginName() { 42 | return pluginName; 43 | } 44 | 45 | public void setPluginName(String pluginName) { 46 | this.pluginName = pluginName; 47 | } 48 | 49 | public String getAddress() { 50 | return address; 51 | } 52 | 53 | public void setAddress(String address) { 54 | this.address = address; 55 | } 56 | 57 | public String getDescription() { 58 | return description; 59 | } 60 | 61 | public void setDescription(String description) { 62 | this.description = description; 63 | } 64 | 65 | public List getAppArkList() { 66 | return appArkList; 67 | } 68 | 69 | public void setAppArkList(List appArkList) { 70 | this.appArkList = appArkList; 71 | } 72 | 73 | public List getVersions() { 74 | return versions; 75 | } 76 | 77 | public void setVersions(List versions) { 78 | this.versions = versions; 79 | } 80 | 81 | public static class Version { 82 | 83 | private String version; 84 | 85 | private String sourcePath; 86 | 87 | public String getVersion() { 88 | return version; 89 | } 90 | 91 | public void setVersion(String version) { 92 | this.version = version; 93 | } 94 | 95 | public String getSourcePath() { 96 | return sourcePath; 97 | } 98 | 99 | public void setSourcePath(String sourcePath) { 100 | this.sourcePath = sourcePath; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/model/ClientResponseModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import com.alipay.sofa.ark.api.ResponseCode; 20 | 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | 24 | /** 25 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/17 10:29 PM 26 | * @since: 27 | **/ 28 | public class ClientResponseModel { 29 | 30 | private String message = ""; 31 | private ResponseCode code = ResponseCode.NOT_FOUND_BIZ; 32 | private Set bizInfos = new HashSet<>(); 33 | 34 | public String getMessage() { 35 | return message; 36 | } 37 | 38 | public void setMessage(String message) { 39 | this.message = message; 40 | } 41 | 42 | public ResponseCode getCode() { 43 | return code; 44 | } 45 | 46 | public void setCode(ResponseCode code) { 47 | this.code = code; 48 | } 49 | 50 | public Set getBizInfos() { 51 | return bizInfos; 52 | } 53 | 54 | public void setBizInfos(Set bizInfos) { 55 | this.bizInfos = bizInfos; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-arkmng/src/main/java/com/alipay/sofa/dashboard/service/ArkMngService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.service; 18 | 19 | import com.alipay.sofa.dashboard.model.AppArkDO; 20 | import com.alipay.sofa.dashboard.model.ArkPluginDO; 21 | import com.alipay.sofa.dashboard.model.ArkPluginModel; 22 | 23 | import java.util.List; 24 | 25 | /** 26 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/19 上午11:13 27 | * @since: 28 | **/ 29 | public interface ArkMngService { 30 | 31 | /** 32 | * 获取当前所有注册的 plugin 信息 33 | * 34 | * @return 35 | */ 36 | List fetchRegisteredPlugins(); 37 | 38 | /** 39 | * 向管控端注册插件 40 | * 41 | * @param model 42 | * @return 43 | */ 44 | boolean registerPlugin(ArkPluginDO model); 45 | 46 | /** 47 | * 更新插件 48 | * @param model 49 | * @return 50 | */ 51 | boolean updatePlugin(ArkPluginDO model); 52 | 53 | /** 54 | * 给模块增加新的版本 55 | * 56 | * @param mId 57 | * @param version 58 | * @param address 59 | * @return 60 | */ 61 | boolean addNewVersion(int mId, String version, String address); 62 | 63 | /** 64 | * 删除插件版本 65 | * @param mId 66 | * @param version 67 | * @return 68 | */ 69 | boolean deleteVersion(int mId, String version); 70 | 71 | /** 72 | * 删除一个模块 73 | * @param mId 74 | * @return 75 | */ 76 | boolean removePlugins(int mId); 77 | 78 | /** 79 | * 通过插件名查询插件 80 | * 81 | * @param pluginName 82 | * @return 83 | */ 84 | List fetchPluginsByName(String pluginName); 85 | 86 | /** 87 | * 关联应用和插件 88 | * 89 | * @param moduleId 90 | * @param appName 91 | * @return 92 | */ 93 | int relatedAppToPlugin(int moduleId, String appName); 94 | 95 | /** 96 | * 根据插件名查询当前插件关联的应用名 97 | * 98 | * @param pluginName 99 | * @return 100 | */ 101 | List queryAppsByPlugin(String pluginName); 102 | 103 | /** 104 | * 取消 105 | * 106 | * @param appName 107 | * @param pluginName 108 | * @return 109 | */ 110 | int cancelRelatedAppToPlugin(String pluginName, String appName); 111 | 112 | } 113 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofa-dashboard-backend 7 | com.alipay.sofa 8 | 1.0.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | sofa-dashboard-core 14 | 15 | 16 | ../../ 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | com.alipay.sofa 26 | dashboard-client-core 27 | 28 | 29 | com.google.guava 30 | guava 31 | 32 | 33 | org.apache.curator 34 | curator-framework 35 | 36 | 37 | org.apache.curator 38 | curator-recipes 39 | 40 | 41 | com.alibaba 42 | fastjson 43 | 44 | 45 | com.alipay.sofa.common 46 | sofa-common-tools 47 | 48 | 49 | com.alipay.sofa 50 | sofa-ark-api 51 | 52 | 53 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/callback/BizStateCallable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.callback; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | 22 | import java.util.concurrent.Callable; 23 | import java.util.concurrent.ExecutorService; 24 | import java.util.concurrent.Executors; 25 | import java.util.concurrent.Future; 26 | import java.util.concurrent.TimeUnit; 27 | 28 | /** 29 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/20 10:49 AM 30 | * @since: 31 | **/ 32 | public class BizStateCallable implements Callable { 33 | 34 | private static final Logger LOGGER = LoggerFactory.getLogger(BizStateCallable.class); 35 | 36 | private static final ExecutorService executor = Executors.newSingleThreadExecutor(); 37 | 38 | private final Callable callable; 39 | private final V timeoutV; 40 | /** 2s */ 41 | private final long timeout; 42 | 43 | /** 44 | * 构造一个 TimeoutCallable 45 | * 46 | * @param callable 要运行的 Callable 47 | * @param timeout Callable 的最大运行时间 48 | * @param timeoutV Callable 超时的返回结果 49 | */ 50 | public BizStateCallable(Callable callable, long timeout, V timeoutV) { 51 | this.timeout = timeout; 52 | this.callable = callable; 53 | this.timeoutV = timeoutV; 54 | } 55 | 56 | @Override 57 | public V call() { 58 | Future future = executor.submit(callable); 59 | V v = null; 60 | try { 61 | v = future.get(timeout, TimeUnit.SECONDS); 62 | } catch (Throwable ex) { 63 | LOGGER.error("biz state callback timeout or get error.", ex); 64 | } 65 | executor.shutdownNow(); // 给线程池中所有正在运行的线程发送 中断 信号 66 | return v != null ? v : timeoutV; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/constants/enums/ResponseCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.constants.enums; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/16 12:06 PM 21 | * @since: 22 | **/ 23 | public enum ResponseCode { 24 | SUCCESS, FAILED, REPEAT_BIZ, NOT_FOUND_BIZ, ILLEGAL_STATE_BIZ; 25 | } 26 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/AppModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/8/26 10:35 AM 21 | * @since: 22 | **/ 23 | public class AppModel { 24 | 25 | private String name; 26 | private String host; 27 | private int port; 28 | private String state; 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getHost() { 39 | return host; 40 | } 41 | 42 | public void setHost(String host) { 43 | this.host = host; 44 | } 45 | 46 | public int getPort() { 47 | return port; 48 | } 49 | 50 | public void setPort(int port) { 51 | this.port = port; 52 | } 53 | 54 | public String getState() { 55 | return state; 56 | } 57 | 58 | public void setState(String state) { 59 | this.state = state; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/ApplicationInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.Objects; 20 | 21 | /** 22 | * 引用运行状态概况 23 | * 24 | * @author guolei.sgl (guolei.sgl@antfin.com) 2019/7/14 10:38 AM 25 | **/ 26 | public class ApplicationInfo implements Comparable { 27 | 28 | /** 29 | * 服务名称 30 | */ 31 | private String applicationName; 32 | 33 | /** 34 | * 运行实例总数 35 | */ 36 | private int applicationCount; 37 | 38 | public String getApplicationName() { 39 | return applicationName; 40 | } 41 | 42 | public void setApplicationName(String applicationName) { 43 | this.applicationName = applicationName; 44 | } 45 | 46 | public int getApplicationCount() { 47 | return applicationCount; 48 | } 49 | 50 | public void setApplicationCount(int applicationCount) { 51 | this.applicationCount = applicationCount; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "AppStatistic{" + "applicationName='" + applicationName + '\'' 57 | + ", applicationCount=" + applicationCount + '}'; 58 | } 59 | 60 | @Override 61 | public boolean equals(Object o) { 62 | if (this == o) 63 | return true; 64 | if (o == null || getClass() != o.getClass()) 65 | return false; 66 | ApplicationInfo statistic = (ApplicationInfo) o; 67 | return getApplicationCount() == statistic.getApplicationCount() 68 | && Objects.equals(getApplicationName(), statistic.getApplicationName()); 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | return Objects.hash(getApplicationName(), getApplicationCount()); 74 | } 75 | 76 | @Override 77 | public int compareTo(ApplicationInfo o) { 78 | return applicationName.compareTo(o.applicationName); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/CommandRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/10 下午10:08 23 | * @since: 24 | **/ 25 | public class CommandRequest { 26 | 27 | /** 28 | * 命令推送维度 29 | */ 30 | private String dimension; 31 | 32 | /** 33 | * 命令 34 | */ 35 | private String command; 36 | /** 37 | * 目标主机 38 | */ 39 | private List targetHost; 40 | 41 | /** 42 | * 插件名 43 | */ 44 | private String pluginName; 45 | 46 | /** 47 | * 插件版本 48 | */ 49 | private String pluginVersion; 50 | 51 | /** 52 | * 宿主应用名 53 | */ 54 | private String appName; 55 | 56 | public String getDimension() { 57 | return dimension; 58 | } 59 | 60 | public void setDimension(String dimension) { 61 | this.dimension = dimension; 62 | } 63 | 64 | public String getCommand() { 65 | return command; 66 | } 67 | 68 | public void setCommand(String command) { 69 | this.command = command; 70 | } 71 | 72 | public List getTargetHost() { 73 | return targetHost; 74 | } 75 | 76 | public void setTargetHost(List targetHost) { 77 | this.targetHost = targetHost; 78 | } 79 | 80 | public String getPluginName() { 81 | return pluginName; 82 | } 83 | 84 | public void setPluginName(String pluginName) { 85 | this.pluginName = pluginName; 86 | } 87 | 88 | public String getPluginVersion() { 89 | return pluginVersion; 90 | } 91 | 92 | public void setPluginVersion(String pluginVersion) { 93 | this.pluginVersion = pluginVersion; 94 | } 95 | 96 | public String getAppName() { 97 | return appName; 98 | } 99 | 100 | public void setAppName(String appName) { 101 | this.appName = appName; 102 | } 103 | 104 | @Override 105 | public String toString() { 106 | return "CommandRequest{" + "dimension='" + dimension + '\'' + ", command='" + command 107 | + '\'' + ", targetHost=" + targetHost + ", pluginName='" + pluginName + '\'' 108 | + ", pluginVersion='" + pluginVersion + '\'' + ", appName='" + appName + '\'' + '}'; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/ServiceAppModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/14 11:04 AM 23 | * @since: 24 | **/ 25 | public class ServiceAppModel { 26 | private List providers; 27 | private List consumers; 28 | 29 | public List getProviders() { 30 | return providers; 31 | } 32 | 33 | public void setProviders(List providers) { 34 | this.providers = providers; 35 | } 36 | 37 | public List getConsumers() { 38 | return consumers; 39 | } 40 | 41 | public void setConsumers(List consumers) { 42 | this.consumers = consumers; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/ServiceModel.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 18/12/7 下午2:07 21 | * @since: 22 | **/ 23 | public class ServiceModel { 24 | private String serviceId; 25 | 26 | private String serviceProviderAppName; 27 | 28 | private String serviceProviderAppNum; 29 | 30 | private String serviceConsumerAppNum; 31 | 32 | public String getServiceId() { 33 | return serviceId; 34 | } 35 | 36 | public void setServiceId(String serviceId) { 37 | this.serviceId = serviceId; 38 | } 39 | 40 | public String getServiceProviderAppName() { 41 | return serviceProviderAppName; 42 | } 43 | 44 | public void setServiceProviderAppName(String serviceProviderAppName) { 45 | this.serviceProviderAppName = serviceProviderAppName; 46 | } 47 | 48 | public String getServiceProviderAppNum() { 49 | return serviceProviderAppNum; 50 | } 51 | 52 | public void setServiceProviderAppNum(String serviceProviderAppNum) { 53 | this.serviceProviderAppNum = serviceProviderAppNum; 54 | } 55 | 56 | public String getServiceConsumerAppNum() { 57 | return serviceConsumerAppNum; 58 | } 59 | 60 | public void setServiceConsumerAppNum(String serviceConsumerAppNum) { 61 | this.serviceConsumerAppNum = serviceConsumerAppNum; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/model/StampedValueEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.io.Serializable; 20 | 21 | /** 22 | * 待时间戳的数值记录 23 | * 24 | * @param 数值模型 25 | */ 26 | public class StampedValueEntity implements Serializable { 27 | 28 | private static final int serialVersionUID = 0x11; 29 | 30 | /** 31 | * 获取时间戳 32 | */ 33 | private String timestamp; 34 | 35 | /** 36 | * 数据名称 37 | */ 38 | private String name; 39 | 40 | /** 41 | * 数据值描述 42 | */ 43 | private T value; 44 | 45 | public String getTimestamp() { 46 | return timestamp; 47 | } 48 | 49 | public void setTimestamp(String timestamp) { 50 | this.timestamp = timestamp; 51 | } 52 | 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | public void setName(String name) { 58 | this.name = name; 59 | } 60 | 61 | public T getValue() { 62 | return value; 63 | } 64 | 65 | public void setValue(T value) { 66 | this.value = value; 67 | } 68 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/spi/AppService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.spi; 18 | 19 | import com.alipay.sofa.dashboard.client.model.common.Application; 20 | import com.alipay.sofa.dashboard.model.ApplicationInfo; 21 | import org.springframework.lang.NonNull; 22 | import org.springframework.lang.Nullable; 23 | 24 | import java.util.List; 25 | 26 | /** 27 | * 应用实例统计服务 28 | * 29 | * @author chen.pengzhi (chpengzh@foxmail.com) 30 | */ 31 | public interface AppService { 32 | 33 | /** 34 | * 获取全部应用统计信息 35 | * 36 | * @return 全部应用统计信息,如果没有实例则返回空列表 37 | */ 38 | @NonNull 39 | List getAllStatistics(); 40 | 41 | /** 42 | * 获取包含关键词的应用统计信息 43 | * 44 | * @param keyword 关键词,如果为空,则返回全部统计信息 45 | * @return 满足条件应用统计信息,如果没有实例则返回空列表 46 | */ 47 | @NonNull 48 | List getStatisticsByKeyword(@Nullable String keyword); 49 | 50 | /** 51 | * 获取全部应用实例信息 52 | * 53 | * @return 全部应用实例信息, 如果没有实例则返回空列表 54 | */ 55 | @NonNull 56 | List getAllInstances(); 57 | 58 | /** 59 | * 获取服务名匹配的全部实例信息, 如果查询名为空,则返回全部实例信息 60 | * 61 | * @param serviceName 服务名称 62 | * @return 满足条件应用实例信息,如果没有实例则返回空列表 63 | */ 64 | @NonNull 65 | List getInstancesByName(@Nullable String serviceName); 66 | } 67 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/spi/ApplicationManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.spi; 18 | 19 | import com.alipay.sofa.dashboard.model.AppModel; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/8/26 10:35 AM 25 | * @since: 26 | **/ 27 | public interface ApplicationManager { 28 | 29 | List applications(); 30 | } 31 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/spi/CommandPushManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.spi; 18 | 19 | import com.alipay.sofa.dashboard.model.CommandRequest; 20 | 21 | /** 22 | * CommandPushManager can be extended by any other external user to implement push of ark commands, 23 | * such as zookeeper-based push by default, or you can implement it based on Apollo. 24 | * 25 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/18 下午2:49 26 | * @since: 27 | **/ 28 | public interface CommandPushManager { 29 | 30 | /** 31 | * 命令推送扩展接口 32 | * 33 | * @param command 34 | */ 35 | void pushCommand(CommandRequest command); 36 | } 37 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/spi/MonitorService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.spi; 18 | 19 | import com.alipay.sofa.dashboard.client.model.common.HostAndPort; 20 | import com.alipay.sofa.dashboard.client.model.env.EnvironmentDescriptor; 21 | import com.alipay.sofa.dashboard.client.model.health.HealthDescriptor; 22 | import com.alipay.sofa.dashboard.client.model.info.InfoDescriptor; 23 | import com.alipay.sofa.dashboard.client.model.logger.LoggersDescriptor; 24 | import com.alipay.sofa.dashboard.client.model.mappings.MappingsDescriptor; 25 | import com.alipay.sofa.dashboard.client.model.memory.MemoryDescriptor; 26 | import com.alipay.sofa.dashboard.client.model.thread.ThreadSummaryDescriptor; 27 | import com.alipay.sofa.dashboard.model.StampedValueEntity; 28 | import org.springframework.lang.NonNull; 29 | import org.springframework.lang.Nullable; 30 | 31 | import java.util.List; 32 | 33 | /** 34 | * 应用实例统计面板信息 35 | * 36 | * @author chen.pengzhi (chpengzh@foxmail.com) 37 | */ 38 | public interface MonitorService { 39 | 40 | /** 41 | * 获取应用环境变量描述. 42 | * 43 | * @param hostAndPort 实例地址 44 | * @return 实例环境变量信息,如果无数据则返回{@code null} 45 | */ 46 | @Nullable 47 | EnvironmentDescriptor fetchEnvironment(@NonNull HostAndPort hostAndPort); 48 | 49 | /** 50 | * 获取应用实例的健康度信息. 51 | * 52 | * @param hostAndPort 实例地址 53 | * @return 实例健康度信息,如果无数据则返回{@code null} 54 | */ 55 | @Nullable 56 | HealthDescriptor fetchHealth(@NonNull HostAndPort hostAndPort); 57 | 58 | /** 59 | * 获取应用实例描述. 60 | * 61 | * @param hostAndPort 实例地址 62 | * @return 实例描述, 如果无数据则返回{@code null} 63 | */ 64 | @Nullable 65 | InfoDescriptor fetchInfo(@NonNull HostAndPort hostAndPort); 66 | 67 | /** 68 | * 获取应用的logger信息. 69 | * 70 | * @param hostAndPort 实例地址 71 | * @return logger信息, 如果无数据则返回{@code null} 72 | */ 73 | @Nullable 74 | LoggersDescriptor fetchLoggers(@NonNull HostAndPort hostAndPort); 75 | 76 | /** 77 | * 获取引用的mapping信息 78 | * 79 | * @param hostAndPort 实例地址 80 | * @return mapping信息, 如果无数据则返回{@code null} 81 | */ 82 | @Nullable 83 | MappingsDescriptor fetchMappings(@NonNull HostAndPort hostAndPort); 84 | 85 | /** 86 | * 获取过去一段时间的线程概况统计信息(按照时间升序排序). 87 | * 88 | * @param hostAndPort 实例地址 89 | * @return 线程概况统计信息, 如果数据为空则返回空列表 90 | */ 91 | @NonNull 92 | List> fetchThreadInfo(@NonNull HostAndPort hostAndPort); 93 | 94 | /** 95 | * 获取过去一段时间的内存概况统计信息(按照时间升序排序). 96 | * 97 | * @param hostAndPort 实例地址 98 | * @return 内存概况统计信息,如果数据为空则返回空列表 99 | */ 100 | @NonNull 101 | List> fetchMemoryInfo(@NonNull HostAndPort hostAndPort); 102 | 103 | } 104 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/utils/FastJsonUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | 21 | /** 22 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/16 8:52 PM 23 | * @since: 24 | **/ 25 | public class FastJsonUtils { 26 | 27 | public static String getString(JSONObject json, String path) { 28 | return get(json, path, String.class); 29 | } 30 | 31 | public static Integer getInteger(JSONObject json, String path) { 32 | return get(json, path, Integer.class); 33 | } 34 | 35 | public static T get(JSONObject json, String path, Class t) { 36 | if (path.startsWith("/")) { 37 | path = path.substring(1); 38 | } 39 | String[] nodes = path.split("/"); 40 | JSONObject tmp = json; 41 | for (int i = 0; i < nodes.length - 1; i++) { 42 | tmp = tmp.getJSONObject(nodes[i]); 43 | } 44 | String key = nodes[nodes.length - 1]; 45 | if (t == String.class) { 46 | return (T) tmp.getString(key); 47 | } else if (t == Integer.class) { 48 | return (T) tmp.getInteger(key); 49 | } 50 | return (T) tmp.get(key); 51 | } 52 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/utils/ObjectBytesUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import com.alibaba.fastjson.JSON; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.util.StringUtils; 23 | 24 | /** 25 | * Used to convert an Object into a byte array and a byte array into an object 26 | * 27 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/17 下午5:49 28 | * @since: 29 | **/ 30 | public class ObjectBytesUtil { 31 | 32 | private static final Logger LOGGER = LoggerFactory.getLogger(ObjectBytesUtil.class); 33 | 34 | public static T convertFromBytes(byte[] bytes, Class valueType) { 35 | try { 36 | if (bytes == null) { 37 | return null; 38 | } 39 | return JSON.parseObject(bytes, valueType); 40 | } catch (Exception e) { 41 | LOGGER.error("Error to convert object from data bytes.", e); 42 | } 43 | return null; 44 | } 45 | 46 | public static T convertFromString(String input, Class valueType) { 47 | try { 48 | if (StringUtils.isEmpty(input)) { 49 | return null; 50 | } 51 | return JSON.parseObject(input, valueType); 52 | } catch (Exception e) { 53 | LOGGER.error("Error to convert object from data bytes.", e); 54 | } 55 | return null; 56 | } 57 | 58 | public static byte[] convertFromObject(Object obj) { 59 | try { 60 | if (obj == null) { 61 | return null; 62 | } 63 | String jsonObj = JSON.toJSONString(obj); 64 | return jsonObj.getBytes(); 65 | } catch (Exception e) { 66 | LOGGER.error("Error to convert bytes from data object.", e); 67 | } 68 | return null; 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/utils/SofaDashboardUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import java.text.SimpleDateFormat; 20 | import java.util.Date; 21 | 22 | /** 23 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/16 11:28 AM 24 | * @since: 25 | **/ 26 | public class SofaDashboardUtil { 27 | 28 | public static Date now() { 29 | return new Date(System.currentTimeMillis()); 30 | } 31 | 32 | public static String formatDate(Date date) { 33 | SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 34 | return dateFormat.format(date); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-core/src/main/java/com/alipay/sofa/dashboard/zookeeper/ZkCommandClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.zookeeper; 18 | 19 | import org.apache.curator.RetryPolicy; 20 | import org.apache.curator.framework.CuratorFramework; 21 | import org.apache.curator.framework.CuratorFrameworkFactory; 22 | import org.apache.curator.retry.ExponentialBackoffRetry; 23 | import org.springframework.beans.factory.InitializingBean; 24 | import org.springframework.beans.factory.annotation.Value; 25 | import org.springframework.stereotype.Component; 26 | 27 | /** 28 | * Provide an instance of the ZooKeeper client in the Spring application environment 29 | * 30 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/2/15 11:59 AM 31 | * @since: 32 | **/ 33 | @Component 34 | public class ZkCommandClient implements InitializingBean { 35 | 36 | private CuratorFramework curatorClient; 37 | 38 | @Value("${com.alipay.sofa.dashboard.zookeeper.address:localhost:2181}") 39 | private String connectString; 40 | 41 | @Value("${com.alipay.sofa.dashboard.zookeeper.baseSleepTimeMs:1000}") 42 | private int baseSleepTimeMs; 43 | 44 | @Value("${com.alipay.sofa.dashboard.zookeeper.maxRetries:3}") 45 | private int maxRetries; 46 | 47 | @Value("${com.alipay.sofa.dashboard.zookeeper.sessionTimeoutMs:6000}") 48 | private int sessionTimeoutMs; 49 | 50 | @Value("${com.alipay.sofa.dashboard.zookeeper.connectionTimeoutMs:6000}") 51 | private int connectionTimeoutMs; 52 | 53 | @Override 54 | public void afterPropertiesSet() throws Exception { 55 | // custom policy 56 | RetryPolicy retryPolicy = new ExponentialBackoffRetry(baseSleepTimeMs, maxRetries); 57 | // to build curatorClient 58 | curatorClient = CuratorFrameworkFactory.builder().connectString(connectString) 59 | .sessionTimeoutMs(sessionTimeoutMs).connectionTimeoutMs(connectionTimeoutMs) 60 | .retryPolicy(retryPolicy).build(); 61 | curatorClient.start(); 62 | } 63 | 64 | public CuratorFramework getCuratorClient() { 65 | return curatorClient; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofa-dashboard-backend 7 | com.alipay.sofa 8 | 1.0.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | sofa-dashboard-governance 14 | 15 | 16 | ../../ 17 | 18 | 19 | 20 | 21 | com.alipay.sofa 22 | rpc-sofa-boot-starter 23 | 24 | 25 | com.alipay.sofa 26 | sofa-dashboard-core 27 | 28 | 29 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/cache/SofaRegistryDataCacheImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.cache; 18 | 19 | import com.alipay.sofa.dashboard.domain.RpcConsumer; 20 | import com.alipay.sofa.dashboard.domain.RpcProvider; 21 | import com.alipay.sofa.dashboard.domain.RpcService; 22 | import com.alipay.sofa.rpc.common.utils.StringUtils; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.concurrent.ConcurrentHashMap; 28 | 29 | /** 30 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/5/23 10:52 AM 31 | * @since: 32 | **/ 33 | public class SofaRegistryDataCacheImpl implements RegistryDataCache { 34 | 35 | private Map serviceMap = new ConcurrentHashMap<>(); 36 | private Map> consumerMap = new ConcurrentHashMap<>(); 37 | private Map> providerMap = new ConcurrentHashMap<>(); 38 | 39 | @Override 40 | public Map fetchService() { 41 | return serviceMap; 42 | } 43 | 44 | @Override 45 | public List fetchProvidersByService(String serviceName) { 46 | List result = null; 47 | if (StringUtils.isNotBlank(serviceName)) { 48 | result = providerMap.get(serviceName); 49 | } 50 | if (result == null) { 51 | result = new ArrayList<>(); 52 | } 53 | return result; 54 | } 55 | 56 | @Override 57 | public List fetchConsumersByService(String serviceName) { 58 | List result = null; 59 | if (StringUtils.isNotBlank(serviceName)) { 60 | result = consumerMap.get(serviceName); 61 | } 62 | if (result == null) { 63 | result = new ArrayList<>(); 64 | } 65 | return result; 66 | } 67 | 68 | @Override 69 | public void addProviders(String serviceName, List providerList) { 70 | if (StringUtils.isNotBlank(serviceName) && providerList != null) { 71 | providerMap.put(serviceName, providerList); 72 | } 73 | } 74 | 75 | @Override 76 | public void addConsumers(String serviceName, List consumerList) { 77 | if (StringUtils.isNotBlank(serviceName) && consumerList != null) { 78 | consumerMap.put(serviceName, consumerList); 79 | } 80 | } 81 | 82 | @Override 83 | public void addService(List rpcServices) { 84 | for (RpcService rpcService : rpcServices) { 85 | serviceMap.put(rpcService.getServiceName(), rpcService); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/domain/RpcService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.domain; 18 | 19 | import java.io.Serializable; 20 | 21 | /** 22 | * @author bystander 23 | * @version $Id: Service.java, v 0.1 2018年12月10日 23:43 bystander Exp $ 24 | */ 25 | public class RpcService implements Serializable { 26 | 27 | private String serviceName; 28 | 29 | private String appName; 30 | 31 | private String group; 32 | 33 | private String version; 34 | 35 | public String getServiceName() { 36 | return serviceName; 37 | } 38 | 39 | public void setServiceName(String serviceName) { 40 | this.serviceName = serviceName; 41 | } 42 | 43 | public String getAppName() { 44 | return appName; 45 | } 46 | 47 | public void setAppName(String appName) { 48 | this.appName = appName; 49 | } 50 | 51 | public String getGroup() { 52 | return group; 53 | } 54 | 55 | public void setGroup(String group) { 56 | this.group = group; 57 | } 58 | 59 | public String getVersion() { 60 | return version; 61 | } 62 | 63 | public void setVersion(String version) { 64 | this.version = version; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | StringBuilder sb = new StringBuilder("Service{"); 70 | sb.append("serviceName='").append(serviceName).append('\''); 71 | sb.append(", appName='").append(appName).append('\''); 72 | sb.append(", group='").append(group).append('\''); 73 | sb.append(", version='").append(version).append('\''); 74 | sb.append('}'); 75 | return sb.toString(); 76 | } 77 | 78 | @Override 79 | public boolean equals(Object o) { 80 | if (this == o) { 81 | return true; 82 | } 83 | if (!(o instanceof RpcService)) { 84 | return false; 85 | } 86 | 87 | RpcService that = (RpcService) o; 88 | 89 | if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) { 90 | return false; 91 | } 92 | if (appName != null ? !appName.equals(that.appName) : that.appName != null) { 93 | return false; 94 | } 95 | if (group != null ? !group.equals(that.group) : that.group != null) { 96 | return false; 97 | } 98 | return version != null ? version.equals(that.version) : that.version == null; 99 | } 100 | 101 | @Override 102 | public int hashCode() { 103 | int result = serviceName != null ? serviceName.hashCode() : 0; 104 | result = 31 * result + (appName != null ? appName.hashCode() : 0); 105 | result = 31 * result + (group != null ? group.hashCode() : 0); 106 | result = 31 * result + (version != null ? version.hashCode() : 0); 107 | return result; 108 | } 109 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/listener/ApplicationStartedListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.listener; 18 | 19 | import com.alipay.sofa.dashboard.constants.SofaDashboardConstants; 20 | import com.alipay.sofa.dashboard.sync.RegistryDataSyncManager; 21 | import com.alipay.sofa.rpc.boot.config.RegistryConfigureProcessor; 22 | import com.alipay.sofa.rpc.boot.config.SofaBootRpcConfigConstants; 23 | import com.alipay.sofa.rpc.boot.config.ZookeeperConfigurator; 24 | import com.alipay.sofa.rpc.common.utils.StringUtils; 25 | import com.alipay.sofa.rpc.config.RegistryConfig; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.context.ApplicationEvent; 28 | import org.springframework.context.ApplicationListener; 29 | import org.springframework.context.event.ContextRefreshedEvent; 30 | import org.springframework.core.env.ConfigurableEnvironment; 31 | import org.springframework.core.env.Environment; 32 | import org.springframework.core.env.MapPropertySource; 33 | import org.springframework.core.env.PropertySource; 34 | 35 | import java.util.HashMap; 36 | import java.util.Map; 37 | 38 | /** 39 | * @author bystander 40 | * @version $Id: ApplicationStartedListener.java, v 0.1 2018年12月11日 17:15 bystander Exp $ 41 | */ 42 | public class ApplicationStartedListener implements ApplicationListener { 43 | 44 | @Autowired 45 | private RegistryDataSyncManager registryDataSyncManager; 46 | 47 | @Autowired 48 | private Environment environment; 49 | 50 | @Override 51 | public void onApplicationEvent(ApplicationEvent event) { 52 | if (event instanceof ContextRefreshedEvent) { 53 | String address = environment.getProperty(SofaDashboardConstants.KEY); 54 | if (StringUtils.isNotBlank(address)) { 55 | RegistryConfig registryConfig = new RegistryConfig(); 56 | if (address.startsWith(SofaDashboardConstants.ZOOKEEPER_PREFIX)) { 57 | RegistryConfigureProcessor processor = new ZookeeperConfigurator(); 58 | registryConfig = processor.buildFromAddress(address); 59 | } else if (address.startsWith(SofaDashboardConstants.SOFA_PREFIX)) { 60 | registryConfig.setAddress(address.substring(SofaDashboardConstants.SOFA_PREFIX 61 | .length())); 62 | registryConfig.setProtocol(SofaBootRpcConfigConstants.DEFAULT_REGISTRY); 63 | // config registry type 64 | Map props = new HashMap<>(); 65 | props.put(SofaDashboardConstants.REGISTRY_TYPE, 66 | SofaBootRpcConfigConstants.DEFAULT_REGISTRY); 67 | PropertySource propertySource = new MapPropertySource( 68 | "customRegistryPropertySource", props); 69 | ((ConfigurableEnvironment) environment).getPropertySources().addLast( 70 | propertySource); 71 | } 72 | registryDataSyncManager.start(registryConfig); 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/listener/RegistryDataChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.listener; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author bystander 23 | * @version $Id: RegistryDataChangeListener.java, v 0.1 2018年12月12日 08:07 bystander Exp $ 24 | */ 25 | public interface RegistryDataChangeListener { 26 | 27 | /** 28 | * 数据变更时回调 29 | * 30 | * @param type 31 | * @param data 32 | */ 33 | void onDataChange(String type, List data); 34 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/listener/zookeeper/ServiceNodeChangeListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.listener.zookeeper; 18 | 19 | import org.apache.curator.framework.CuratorFramework; 20 | import org.apache.curator.framework.recipes.cache.PathChildrenCache; 21 | import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; 22 | import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.stereotype.Component; 27 | 28 | /** 29 | * @author bystander 30 | * @version $Id: ServiceNodeChangeListener.java, v 0.1 2018年12月12日 11:25 bystander Exp $ 31 | */ 32 | @Component 33 | public class ServiceNodeChangeListener implements PathChildrenCacheListener { 34 | 35 | private static final Logger LOGGER = LoggerFactory 36 | .getLogger(ServiceNodeChangeListener.class); 37 | private static final String PROVIDERS_KEY = "providers"; 38 | private static final String CONSUMERS_KEY = "consumers"; 39 | 40 | @Autowired 41 | private ProviderNodeChangeListener providerNodeChangeListener; 42 | 43 | @Autowired 44 | private ConsumerNodeChangeListener consumerNodeChangeListener; 45 | 46 | @Override 47 | public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception { 48 | 49 | switch (event.getType()) { 50 | //加了一个provider 51 | case CHILD_ADDED: 52 | if (LOGGER.isDebugEnabled()) { 53 | LOGGER.debug("service event type ={},event={}", event.getType(), 54 | event.getData()); 55 | } 56 | String path = event.getData().getPath(); 57 | 58 | if (path.endsWith(PROVIDERS_KEY)) { 59 | PathChildrenCache cache2 = new PathChildrenCache(client, path, true); 60 | cache2.getListenable().addListener(providerNodeChangeListener); 61 | cache2.start(); 62 | } else if (path.endsWith(CONSUMERS_KEY)) { 63 | PathChildrenCache cache2 = new PathChildrenCache(client, path, true); 64 | cache2.getListenable().addListener(consumerNodeChangeListener); 65 | cache2.start(); 66 | } 67 | break; 68 | //删了一个provider 69 | case CHILD_REMOVED: 70 | if (LOGGER.isDebugEnabled()) { 71 | LOGGER.debug("event type ={},event={}", event.getType(), event.getData()); 72 | } 73 | break; 74 | // 更新一个Provider 75 | case CHILD_UPDATED: 76 | if (LOGGER.isDebugEnabled()) { 77 | LOGGER.debug("event type ={},event={}", event.getType(), event.getData()); 78 | } 79 | break; 80 | default: 81 | break; 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/registry/AdminRegistry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.registry; 18 | 19 | import com.alipay.sofa.dashboard.listener.RegistryDataChangeListener; 20 | import com.alipay.sofa.rpc.config.RegistryConfig; 21 | 22 | /** 23 | * @author bystander 24 | * @version $Id: AdminRegistry.java, v 0.1 2018年12月11日 17:32 bystander Exp $ 25 | */ 26 | public interface AdminRegistry { 27 | 28 | /** 29 | * start 30 | * 31 | * @param registryConfig 32 | * @return 33 | */ 34 | boolean start(RegistryConfig registryConfig); 35 | 36 | /** 37 | * for zk it is path 38 | * 39 | * @param group 40 | * @param listener 41 | * @return 42 | */ 43 | void subscribe(String group, RegistryDataChangeListener listener); 44 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/registry/SofaAdminRegistry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.registry; 18 | 19 | import com.alipay.sofa.dashboard.listener.RegistryDataChangeListener; 20 | import com.alipay.sofa.dashboard.listener.sofa.SofaRegistryRestClient; 21 | import com.alipay.sofa.rpc.config.RegistryConfig; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | 26 | import java.util.concurrent.ScheduledThreadPoolExecutor; 27 | import java.util.concurrent.TimeUnit; 28 | import java.util.concurrent.atomic.AtomicInteger; 29 | 30 | /** 31 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/5/5 10:26 AM 32 | * @since: 33 | **/ 34 | public class SofaAdminRegistry implements AdminRegistry { 35 | 36 | private static final Logger LOGGER = LoggerFactory 37 | .getLogger(SofaAdminRegistry.class); 38 | 39 | private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 40 | 41 | private static AtomicInteger checkSumCode = new AtomicInteger(0); 42 | 43 | @Autowired 44 | private SofaRegistryRestClient restTemplateClient; 45 | 46 | @Override 47 | public boolean start(RegistryConfig registryConfig) { 48 | try { 49 | restTemplateClient.init(registryConfig); 50 | CheckSumTask checkSumTask = new CheckSumTask(); 51 | // 60s 52 | executor.scheduleWithFixedDelay(checkSumTask, 0, 60, TimeUnit.SECONDS); 53 | } catch (Throwable t) { 54 | LOGGER.error("Failed to start sofa registry.", t); 55 | } 56 | return true; 57 | } 58 | 59 | @Override 60 | public void subscribe(String group, RegistryDataChangeListener listener) { 61 | // do nothing 62 | } 63 | 64 | private class CheckSumTask implements Runnable { 65 | @Override 66 | public void run() { 67 | try { 68 | Integer newCheckVal = restTemplateClient.checkSum(); 69 | if (checkSumCode.get() == newCheckVal) { 70 | return; 71 | } 72 | restTemplateClient.syncAllSessionData(); 73 | // update checkSumCode 74 | checkSumCode.compareAndSet(checkSumCode.get(), newCheckVal); 75 | } catch (Throwable t) { 76 | // catch the exception ,avoid scheduler task interrupt 77 | LOGGER.error("Filed to execute CheckSumTask.", t); 78 | } 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/sync/RegistryDataSync.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.sync; 18 | 19 | import com.alipay.sofa.rpc.config.RegistryConfig; 20 | 21 | /** 22 | * @author bystander 23 | * @version $Id: RegistryDataSync.java, v 0.1 2018年12月10日 23:39 bystander Exp $ 24 | */ 25 | public interface RegistryDataSync { 26 | 27 | /** 28 | * 开始数据同步 29 | * 30 | * @param registryConfig 31 | * @return 32 | */ 33 | boolean start(RegistryConfig registryConfig); 34 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/sync/RegistryDataSyncManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.sync; 18 | 19 | import com.alipay.sofa.rpc.config.RegistryConfig; 20 | 21 | /** 22 | * @author bystander 23 | * @version $Id: RegistryDataSyncManager.java, v 0.1 2018年12月11日 17:10 bystander Exp $ 24 | */ 25 | public interface RegistryDataSyncManager { 26 | /** 27 | * 数据同步管理器启动 28 | * 29 | * @param registryConfig 30 | * @return 31 | */ 32 | boolean start(RegistryConfig registryConfig); 33 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/sync/RegistryDataSyncManagerImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.sync; 18 | 19 | import com.alipay.sofa.rpc.config.RegistryConfig; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.stereotype.Service; 23 | 24 | import javax.annotation.Resource; 25 | import java.util.HashMap; 26 | import java.util.Map; 27 | 28 | /** 29 | * @author bystander 30 | * @version $Id: RegistryDataSync.java, v 0.1 2018年12月10日 23:39 bystander Exp $ 31 | */ 32 | 33 | @Service 34 | public class RegistryDataSyncManagerImpl implements RegistryDataSyncManager { 35 | 36 | private final static Logger LOGGER = LoggerFactory 37 | .getLogger(RegistryDataSyncManagerImpl.class); 38 | 39 | @Resource(name = "registrySyncMap") 40 | private Map syncManager = new HashMap<>(); 41 | 42 | @Override 43 | public boolean start(RegistryConfig registryConfig) { 44 | 45 | RegistryDataSync registryDataSync = syncManager.get(registryConfig.getProtocol()); 46 | 47 | if (registryDataSync != null) { 48 | registryDataSync.start(registryConfig); 49 | return true; 50 | } else { 51 | LOGGER.error("registryConfig is {}, not exist in our support list", registryConfig); 52 | return false; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/sync/SofaRegistryDataSync.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.sync; 18 | 19 | import com.alipay.sofa.dashboard.registry.SofaAdminRegistry; 20 | import com.alipay.sofa.rpc.config.RegistryConfig; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | 25 | /** 26 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/5/6 11:13 AM 27 | * @since: 28 | **/ 29 | public class SofaRegistryDataSync implements RegistryDataSync { 30 | 31 | private final static Logger LOGGER = LoggerFactory.getLogger(SofaRegistryDataSync.class); 32 | 33 | @Autowired 34 | private SofaAdminRegistry sofaAdminRegistry; 35 | 36 | @Override 37 | public boolean start(RegistryConfig registryConfig) { 38 | 39 | LOGGER.info("start sofa registry data sync,config is {}", registryConfig.getAddress()); 40 | sofaAdminRegistry.start(registryConfig); 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-governance/src/main/java/com/alipay/sofa/dashboard/sync/ZookeeperRegistryDataSync.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.sync; 18 | 19 | import com.alipay.sofa.dashboard.constants.SofaDashboardConstants; 20 | import com.alipay.sofa.dashboard.registry.ZookeeperAdminRegistry; 21 | import com.alipay.sofa.rpc.config.RegistryConfig; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | 26 | /** 27 | * @author bystander 28 | * @version $Id: ZookeeperRegistryDataSync.java, v 0.1 2018年12月10日 23:39 bystander Exp $ 29 | */ 30 | public class ZookeeperRegistryDataSync implements RegistryDataSync { 31 | private final static Logger LOGGER = LoggerFactory 32 | .getLogger(ZookeeperRegistryDataSync.class); 33 | 34 | @Autowired 35 | private ZookeeperAdminRegistry zookeeperAdminRegistry; 36 | 37 | @Override 38 | public boolean start(RegistryConfig registryConfig) { 39 | 40 | LOGGER.info("start zookeeper registry data sync,config is {}", registryConfig.getAddress()); 41 | zookeeperAdminRegistry.start(registryConfig); 42 | zookeeperAdminRegistry.subscribe(SofaDashboardConstants.DEFAULT_GROUP, 43 | (type, data) -> LOGGER.info("data add,data is {}", data)); 44 | return true; 45 | } 46 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/SofaAdminServerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | import org.springframework.boot.autoconfigure.SpringBootApplication; 21 | 22 | /** 23 | * @author: guolei.sgl (guolei.sgl@antfin.com) 19/1/10 下午9:36 24 | * @since: 25 | **/ 26 | @SpringBootApplication 27 | public class SofaAdminServerApplication { 28 | 29 | public static void main(String[] args) { 30 | SpringApplication.run(SofaAdminServerApplication.class, args); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/configuration/CorsConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.configuration; 18 | 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 21 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 22 | 23 | /** 24 | * CORSConfiguration 25 | * 解决跨域问题 26 | * 27 | * @version 1.0 28 | * @author: guolei.sgl 29 | **/ 30 | @Configuration 31 | public class CorsConfiguration implements WebMvcConfigurer { 32 | @Override 33 | public void addCorsMappings(CorsRegistry registry) { 34 | registry.addMapping("/**").allowedMethods("*").allowedOrigins("*").allowedHeaders("*"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/controller/ApplicationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.controller; 18 | 19 | import com.alipay.sofa.dashboard.model.ApplicationInfo; 20 | import com.alipay.sofa.dashboard.spi.AppService; 21 | import com.alipay.sofa.rpc.common.utils.StringUtils; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.web.bind.annotation.GetMapping; 24 | import org.springframework.web.bind.annotation.RequestMapping; 25 | import org.springframework.web.bind.annotation.RequestParam; 26 | import org.springframework.web.bind.annotation.RestController; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * @author guolei.sgl (guolei.sgl@antfin.com) 18/12/7 下午5:15 32 | */ 33 | @RestController 34 | @RequestMapping("/api/application") 35 | public class ApplicationController { 36 | 37 | @Autowired 38 | private AppService appService; 39 | 40 | @GetMapping 41 | public List getApplication(@RequestParam(value = "keyword", required = false) String keyword) { 42 | return StringUtils.isEmpty(keyword) ? appService.getAllStatistics() : appService 43 | .getStatisticsByKeyword(keyword); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/model/InstanceRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import com.alipay.sofa.dashboard.client.model.common.Application; 20 | import com.alipay.sofa.dashboard.client.model.common.HostAndPort; 21 | import com.alipay.sofa.dashboard.utils.HostPortUtils; 22 | 23 | /** 24 | * @author chen.pengzhi (chpengzh@foxmail.com) 25 | */ 26 | public class InstanceRecord extends Application { 27 | 28 | public InstanceRecord() { 29 | } 30 | 31 | public InstanceRecord(Application other) { 32 | setAppName(other.getAppName()); 33 | setHostName(other.getHostName()); 34 | setInternalHost(other.getInternalHost()); 35 | setPort(other.getPort()); 36 | setAppState(other.getAppState()); 37 | setStartTime(other.getStartTime()); 38 | setLastRecover(other.getLastRecover()); 39 | } 40 | 41 | /** 42 | * Id 是接口层概念,用来和前端交换一个短的 host&port 描述 43 | * 44 | * @return 唯一id 45 | */ 46 | public String getId() { 47 | return HostPortUtils.uniqueId(new HostAndPort(getHostName(), getInternalHost(), getPort())); 48 | } 49 | 50 | public void setId(String instanceId) { 51 | // Do nothing for json serializer 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/model/RecordResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import java.io.Serializable; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | /** 25 | * @author chen.pengzhi (chpengzh@foxmail.com) 26 | */ 27 | public class RecordResponse implements Serializable { 28 | 29 | private static final int serialVersionUID = 0x11; 30 | 31 | private final List overview = new ArrayList<>(); 32 | 33 | private TreeNode detail; 34 | 35 | private RecordResponse(Builder builder) { 36 | this.overview.addAll(builder.overview); 37 | setDetail(builder.detail); 38 | } 39 | 40 | public static Builder newBuilder() { 41 | return new Builder(); 42 | } 43 | 44 | public TreeNode getDetail() { 45 | return detail; 46 | } 47 | 48 | public void setDetail(TreeNode detail) { 49 | this.detail = detail; 50 | } 51 | 52 | public List getOverview() { 53 | return overview; 54 | } 55 | 56 | public static class Overview implements Serializable { 57 | 58 | private static final int serialVersionUID = 0x11; 59 | 60 | private String key; 61 | 62 | private String value; 63 | 64 | public Overview() { 65 | } 66 | 67 | public Overview(String key, String value) { 68 | this.key = key; 69 | this.value = value; 70 | } 71 | 72 | public String getKey() { 73 | return key; 74 | } 75 | 76 | public void setKey(String key) { 77 | this.key = key; 78 | } 79 | 80 | public String getValue() { 81 | return value; 82 | } 83 | 84 | public void setValue(String value) { 85 | this.value = value; 86 | } 87 | } 88 | 89 | public static final class Builder { 90 | 91 | private final List overview = new ArrayList<>(); 92 | 93 | private TreeNode detail; 94 | 95 | private Builder() { 96 | } 97 | 98 | public Builder overview(String key, String value) { 99 | this.overview.add(new Overview(key, value)); 100 | return this; 101 | } 102 | 103 | public Builder overview(Map overviews) { 104 | overviews.forEach((k, v) -> this.overview.add(new Overview(k, String.valueOf(v)))); 105 | return this; 106 | } 107 | 108 | public Builder detail(TreeNode detail) { 109 | this.detail = detail; 110 | return this; 111 | } 112 | 113 | public RecordResponse build() { 114 | return new RecordResponse(this); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/model/TreeNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonInclude; 20 | 21 | import java.io.Serializable; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import java.util.function.Consumer; 25 | 26 | @JsonInclude(JsonInclude.Include.NON_NULL) 27 | public class TreeNode implements Serializable { 28 | 29 | private static final int serialVersionUID = 0x11; 30 | 31 | private String name; 32 | 33 | private String value; 34 | 35 | private List children; 36 | 37 | public TreeNode() { 38 | } 39 | 40 | private TreeNode(String name, String value) { 41 | this.name = name; 42 | this.value = value; 43 | } 44 | 45 | public static TreeNode create(String name, String value) { 46 | return new TreeNode(name, value); 47 | } 48 | 49 | public TreeNode child(TreeNode node) { 50 | if (this.children == null) { 51 | this.children = new ArrayList<>(); 52 | } 53 | this.children.add(node); 54 | return this; 55 | } 56 | 57 | public TreeNode child(String name, String value) { 58 | if (this.children == null) { 59 | this.children = new ArrayList<>(); 60 | } 61 | this.children.add(new TreeNode(name, value)); 62 | return this; 63 | } 64 | 65 | public TreeNode child(String name, Consumer childrenGenerator) { 66 | if (this.children == null) { 67 | this.children = new ArrayList<>(); 68 | } 69 | TreeNode next = new TreeNode(name, null); 70 | childrenGenerator.accept(next); 71 | this.children.add(next); 72 | return this; 73 | } 74 | 75 | public String getName() { 76 | return name; 77 | } 78 | 79 | public void setName(String name) { 80 | this.name = name; 81 | } 82 | 83 | public String getValue() { 84 | return value; 85 | } 86 | 87 | public void setValue(String value) { 88 | this.value = value; 89 | } 90 | 91 | public List getChildren() { 92 | return children; 93 | } 94 | 95 | public void setChildren(List children) { 96 | this.children = children; 97 | } 98 | } -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/response/ResponseEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.response; 18 | 19 | /** 20 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/20 10:44 AM 21 | * @since: 22 | **/ 23 | public class ResponseEntity { 24 | 25 | private boolean success = true; 26 | 27 | private String error = ""; 28 | 29 | private T data; 30 | 31 | public boolean isSuccess() { 32 | return success; 33 | } 34 | 35 | public void setSuccess(boolean success) { 36 | this.success = success; 37 | } 38 | 39 | public String getError() { 40 | return error; 41 | } 42 | 43 | public void setError(String error) { 44 | this.error = error; 45 | } 46 | 47 | public T getData() { 48 | return data; 49 | } 50 | 51 | public void setData(T data) { 52 | this.data = data; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/java/com/alipay/sofa/dashboard/utils/MapUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import org.springframework.util.StringUtils; 20 | 21 | import java.util.HashMap; 22 | import java.util.Map; 23 | 24 | /** 25 | * @author chen.pengzhi (chpengzh@foxmail.com) 26 | */ 27 | public final class MapUtils { 28 | 29 | private MapUtils() { 30 | } 31 | 32 | /** 33 | * Transform a complex dictionary into flat map 34 | * Sample input: 35 | *
36 |      * {
37 |      *     "a": {
38 |      *         "b": {
39 |      *             "c": "d"
40 |      *         },
41 |      *         "e": "f"
42 |      *     }
43 |      * }
44 |      * 
45 | * Sample output: 46 | *
47 |      * {
48 |      *     "a.b.c": "d",
49 |      *     "a.e": "f"
50 |      * }
51 |      * 
52 | * 53 | * @param origin origin map 54 | * @return flat map 55 | */ 56 | public static Map toFlatMap(Map origin) { 57 | return toFlatMap(null, origin); 58 | } 59 | 60 | private static Map toFlatMap(String prefix, Map origin) { 61 | Map result = new HashMap<>(); 62 | for (Map.Entry entry : origin.entrySet()) { 63 | String nextKey = StringUtils.isEmpty(prefix) ? entry.getKey() : prefix + "." 64 | + entry.getKey(); 65 | if (entry.getValue() instanceof Map) { 66 | //noinspection unchecked 67 | Map innerResult = toFlatMap(nextKey, 68 | (Map) entry.getValue()); 69 | result.putAll(innerResult); 70 | } else { 71 | result.put(nextKey, entry.getValue()); 72 | } 73 | } 74 | return result; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/resources/application-localhost.properties: -------------------------------------------------------------------------------- 1 | ## ark 管控端配置中心地址 2 | ## mysql 数据库连接属性配置 3 | spring.datasource.url=jdbc:mysql://127.0.0.1:3306/SofaDashboardDB 4 | spring.datasource.username=root 5 | spring.datasource.password=123456 6 | ## zookeeper 注册中心地址 7 | com.alipay.sofa.dashboard.registry=zookeeper://127.0.0.1:2181 8 | com.alipay.sofa.dashboard.redis.host=127.0.0.1 9 | com.alipay.sofa.dashboard.redis.port=6379 10 | com.alipay.sofa.dashboard.zookeeper.address=127.0.0.1:2181 -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # Application Name 2 | spring.application.name=sofa-dashboard 3 | # logging path 4 | logging.path=./logs 5 | logging.level.com.alipay.sofa.dashboard=INFO 6 | 7 | # druid config 8 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 9 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 10 | 11 | #spring.datasource.schema=classpath:import.sql 12 | mybatis.mapperLocations=classpath*:**/mybatis/*Mapper.xml 13 | mybatis.config-location=classpath:spring/mybatis-configuration.xml 14 | 15 | # server port 16 | server.port=8099 17 | 18 | spring.profiles.active=localhost 19 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss.SSS} %-5level %logger{80} - %msg%n 11 | 12 | 13 | 14 | 15 | true 16 | 17 | 18 | error 19 | 20 | 21 | ${logging.path}/dashboard/common-error.log 22 | 23 | 24 | 25 | ${logging.path}/dashboard/common-error.log.%d{yyyy-MM-dd} 26 | 27 | 30 28 | 29 | 30 | 31 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 32 | 33 | UTF-8 34 | 35 | 36 | 37 | 38 | true 39 | 40 | ${logging.level} 41 | 42 | ${logging.path}/dashboard/dashboard-default.log 43 | 44 | 45 | 46 | ${logging.path}/dashboard/dashboard-default.log.%d{yyyy-MM-dd} 47 | 48 | 49 | 30 50 | 51 | 52 | 53 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n 54 | 55 | UTF-8 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/main/resources/spring/mybatis-configuration.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/java/com/alipay/sofa/dashboard/ArkMngServiceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard; 18 | 19 | import com.alipay.sofa.dashboard.base.AbstractTestBase; 20 | import com.alipay.sofa.dashboard.model.ArkPluginDO; 21 | import com.alipay.sofa.dashboard.model.ArkPluginModel; 22 | import com.alipay.sofa.dashboard.service.ArkMngService; 23 | import org.junit.After; 24 | import org.junit.Assert; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | 29 | import java.util.Date; 30 | import java.util.List; 31 | 32 | /** 33 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/22 2:32 PM 34 | * @since: 35 | **/ 36 | public class ArkMngServiceTest extends AbstractTestBase { 37 | 38 | @Autowired 39 | private ArkMngService arkMngService; 40 | 41 | @Before 42 | public void before() { 43 | ArkPluginDO model = new ArkPluginDO(); 44 | model.setCreateTime(new Date()); 45 | model.setDescription("this is test"); 46 | model.setPluginName("test-plugin"); 47 | boolean result = arkMngService.registerPlugin(model); 48 | Assert.assertTrue(result); 49 | } 50 | 51 | @Test 52 | public void testUpdatePlugin() { 53 | ArkPluginDO arkPluginDO = new ArkPluginDO(); 54 | arkPluginDO.setId(getPluginId("test-plugin")); 55 | arkPluginDO.setPluginName("test-plugin1"); 56 | arkMngService.updatePlugin(arkPluginDO); 57 | List result = arkMngService.fetchPluginsByName("test-plugin1"); 58 | Assert.assertTrue(result.size() == 1); 59 | 60 | // reback 61 | arkPluginDO.setPluginName("test-plugin"); 62 | arkMngService.updatePlugin(arkPluginDO); 63 | } 64 | 65 | @Test 66 | public void testRelatedAppToPlugin() { 67 | int effectLine = arkMngService.relatedAppToPlugin(getPluginId("test-plugin"), "test-app"); 68 | Assert.assertTrue(effectLine > 0); 69 | int cancelEffectLine = arkMngService.cancelRelatedAppToPlugin("test-plugin", "test-app"); 70 | Assert.assertTrue(cancelEffectLine > 0); 71 | } 72 | 73 | @Test 74 | public void testAddNewVersion() { 75 | int mId = getPluginId("test-plugin"); 76 | boolean isAdd = arkMngService.addNewVersion(mId, "1.0", "file:///a/b/c"); 77 | Assert.assertTrue(isAdd); 78 | boolean isDelete = arkMngService.deleteVersion(mId, "1.0"); 79 | Assert.assertTrue(isDelete); 80 | } 81 | 82 | private int getPluginId(String pluginName) { 83 | List arkPluginModels = arkMngService.fetchPluginsByName(pluginName); 84 | 85 | return arkPluginModels.get(0).getId(); 86 | } 87 | 88 | @After 89 | public void after() { 90 | List arkPluginModels = arkMngService.fetchPluginsByName("test-plugin"); 91 | arkMngService.removePlugins(arkPluginModels.get(0).getId()); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/java/com/alipay/sofa/dashboard/ZkCommandPushManagerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard; 18 | 19 | import com.alipay.sofa.dashboard.base.AbstractTestBase; 20 | import com.alipay.sofa.dashboard.constants.SofaDashboardConstants; 21 | import com.alipay.sofa.dashboard.impl.ZkCommandPushManager; 22 | import com.alipay.sofa.dashboard.model.CommandRequest; 23 | import org.apache.curator.framework.CuratorFrameworkFactory; 24 | import org.apache.curator.retry.ExponentialBackoffRetry; 25 | import org.apache.zookeeper.CreateMode; 26 | import org.junit.After; 27 | import org.junit.Assert; 28 | import org.junit.Before; 29 | import org.junit.Test; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | 32 | import java.util.ArrayList; 33 | 34 | /** 35 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/22 3:02 PM 36 | * @since: 37 | **/ 38 | public class ZkCommandPushManagerTest extends AbstractTestBase { 39 | 40 | @Autowired 41 | private ZkCommandPushManager zkCommandPushManager; 42 | 43 | @Before 44 | public void before() throws Exception { 45 | // 初始化 zk 节点 46 | client = CuratorFrameworkFactory.newClient("localhost:2181", new ExponentialBackoffRetry( 47 | 1000, 3)); 48 | client.start(); 49 | client 50 | .create() 51 | .creatingParentContainersIfNeeded() 52 | .withMode(CreateMode.PERSISTENT) 53 | .forPath( 54 | SofaDashboardConstants.SOFA_ARK_ROOT + SofaDashboardConstants.SEPARATOR + "testApp", 55 | "".getBytes()); 56 | } 57 | 58 | @After 59 | public void after() { 60 | client.close(); 61 | } 62 | 63 | @Test 64 | public void testPushCommand() throws Exception { 65 | 66 | CommandRequest commandRequest = new CommandRequest(); 67 | commandRequest.setCommand("install"); 68 | commandRequest.setPluginVersion("1.0.0"); 69 | commandRequest.setDimension("app"); 70 | 71 | commandRequest.setPluginName("testPlugin"); 72 | commandRequest.setAppName("testApp"); 73 | zkCommandPushManager.pushCommand(commandRequest); 74 | String path = SofaDashboardConstants.SOFA_ARK_ROOT + SofaDashboardConstants.SEPARATOR 75 | + commandRequest.getAppName(); 76 | byte[] bytes = client.getData().forPath(path); 77 | String data = new String(bytes); 78 | Assert.assertTrue(data.contains("activated")); 79 | 80 | // ip 81 | commandRequest.setDimension("ip"); 82 | ArrayList list = new ArrayList(); 83 | list.add("127.0.0.1"); 84 | commandRequest.setTargetHost(list); 85 | 86 | zkCommandPushManager.pushCommand(commandRequest); 87 | String ipPath = SofaDashboardConstants.SOFA_ARK_ROOT + SofaDashboardConstants.SEPARATOR 88 | + commandRequest.getAppName() + SofaDashboardConstants.SEPARATOR 89 | + "127.0.0.1"; 90 | byte[] ipBytes = client.getData().forPath(ipPath); 91 | String ipData = new String(ipBytes); 92 | Assert.assertTrue(ipData.contains("activated")); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/java/com/alipay/sofa/dashboard/base/AbstractTestBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.base; 18 | 19 | import com.alipay.sofa.dashboard.SofaAdminServerApplication; 20 | import org.apache.curator.framework.CuratorFramework; 21 | import org.apache.curator.test.TestingServer; 22 | import org.apache.zookeeper.CreateMode; 23 | import org.apache.zookeeper.data.Stat; 24 | import org.junit.AfterClass; 25 | import org.junit.BeforeClass; 26 | import org.junit.runner.RunWith; 27 | import org.springframework.boot.test.context.SpringBootTest; 28 | import org.springframework.boot.web.server.LocalServerPort; 29 | import org.springframework.test.context.TestPropertySource; 30 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 31 | import org.springframework.web.client.RestTemplate; 32 | 33 | import java.io.IOException; 34 | 35 | /** 36 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/4/10 1:55 PM 37 | * @since: 38 | **/ 39 | @RunWith(SpringJUnit4ClassRunner.class) 40 | @SpringBootTest(classes = SofaAdminServerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 41 | @TestPropertySource(locations = "classpath:application-test.properties") 42 | public abstract class AbstractTestBase { 43 | 44 | private static TestingServer server; 45 | 46 | protected CuratorFramework client; 47 | 48 | protected RestTemplate restTemplate; 49 | 50 | @LocalServerPort 51 | protected int definedPort; 52 | 53 | @BeforeClass 54 | public static void setUpBeforeClass() throws Exception { 55 | server = new TestingServer(2181, true); 56 | server.start(); 57 | 58 | } 59 | 60 | @AfterClass 61 | public static void tearDownAfterClass() throws IOException { 62 | server.stop(); 63 | } 64 | 65 | protected void createNode(String path, byte[] data, CreateMode mode) throws Exception { 66 | Stat stat = client.checkExists().forPath(path); 67 | if (stat == null) { 68 | client.create().creatingParentContainersIfNeeded().withMode(mode).forPath(path, data); 69 | } 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/java/com/alipay/sofa/dashboard/utils/FastJsonUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import com.alibaba.fastjson.JSONObject; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | /** 24 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/22 11:42 AM 25 | * @since: 26 | **/ 27 | public class FastJsonUtilsTest { 28 | 29 | @Test 30 | public void testFastJsonUtils() { 31 | JSONObject parent = new JSONObject(); 32 | JSONObject child = new JSONObject(); 33 | child.put("childKey", "childValue"); 34 | child.put("childKeyInteger", 1); 35 | parent.put("parentKeySub", child); 36 | parent.put("parentKeyString", "String"); 37 | parent.put("parentKeyInteger", 1); 38 | 39 | Assert.assertTrue(FastJsonUtils.getString(parent, "parentKeyString").equals("String")); 40 | Assert.assertTrue(FastJsonUtils.getString(parent, "parentKeySub/childKey").equals( 41 | "childValue")); 42 | 43 | Assert.assertTrue(FastJsonUtils.getInteger(parent, "parentKeyInteger") == 1); 44 | Assert.assertTrue(FastJsonUtils.getInteger(parent, "parentKeySub/childKeyInteger") == 1); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/java/com/alipay/sofa/dashboard/utils/SofaDashboardUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.alipay.sofa.dashboard.utils; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | import java.util.Date; 23 | 24 | /** 25 | * @author: guolei.sgl (guolei.sgl@antfin.com) 2019/7/22 11:48 AM 26 | * @since: 27 | **/ 28 | public class SofaDashboardUtilTest { 29 | 30 | @Test 31 | public void testFormatDate() { 32 | Date now = SofaDashboardUtil.now(); 33 | String s = SofaDashboardUtil.formatDate(now); 34 | Assert.assertTrue(s != null); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/resources/SofaDashboardDB.sql: -------------------------------------------------------------------------------- 1 | -- H2 测试SQL,移除了 sql/SofaDashboardDB.sql 里面的建库语句和 2 | -- 表的 COMMENT 在中文情况下会报错,故移除 3 | -- ---------------------------- 4 | -- Table structure for ark_module_app 5 | -- ---------------------------- 6 | DROP TABLE IF EXISTS `ark_module_app`; 7 | CREATE TABLE `ark_module_app` ( 8 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块应用主键', 9 | `module_id` int(11) NOT NULL COMMENT '模块id', 10 | `app_name` varchar(128) NOT NULL COMMENT '应用名', 11 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '模块创建时间', 12 | PRIMARY KEY (`id`) 13 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4; 14 | 15 | -- ---------------------------- 16 | -- Table structure for ark_module_info 17 | -- ---------------------------- 18 | DROP TABLE IF EXISTS `ark_module_info`; 19 | CREATE TABLE `ark_module_info` ( 20 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块主键', 21 | `plugin_name` varchar(128) NOT NULL COMMENT '模块名', 22 | `description` varchar(128) DEFAULT '' COMMENT '模块描述', 23 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '模块创建时间', 24 | PRIMARY KEY (`id`) 25 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 ; 26 | 27 | -- ---------------------------- 28 | -- Table structure for ark_module_user 29 | -- ---------------------------- 30 | DROP TABLE IF EXISTS `ark_module_user`; 31 | CREATE TABLE `ark_module_user` ( 32 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块负责人表主键', 33 | `module_id` int(11) NOT NULL COMMENT '插件模块id', 34 | `user_id` int(11) DEFAULT NULL COMMENT '插件ownerId', 35 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 36 | PRIMARY KEY (`id`) 37 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 ; 38 | 39 | -- ---------------------------- 40 | -- Table structure for ark_module_version 41 | -- ---------------------------- 42 | DROP TABLE IF EXISTS `ark_module_version`; 43 | CREATE TABLE `ark_module_version` ( 44 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块版本表主键', 45 | `module_id` int(11) NOT NULL COMMENT '模块id', 46 | `module_version` varchar(64) NOT NULL COMMENT '模块版本', 47 | `source_path` varchar(64) DEFAULT '' COMMENT '资源路径', 48 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 49 | `is_release` tinyint(4) DEFAULT 0 COMMENT '是否发布', 50 | PRIMARY KEY (`id`) 51 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4; 52 | 53 | -- ---------------------------- 54 | -- Table structure for sofa_dashboard_user 55 | -- ---------------------------- 56 | DROP TABLE IF EXISTS `sofa_dashboard_user`; 57 | CREATE TABLE `sofa_dashboard_user` ( 58 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户表id', 59 | `nick_name` varchar(64) DEFAULT '' COMMENT '昵称', 60 | `email` varchar(64) DEFAULT '' COMMENT '用户邮箱', 61 | `phone` varchar(12) DEFAULT '' COMMENT '用户电话', 62 | `password` varchar(32) DEFAULT '' COMMENT '用户密码', 63 | `header_img_url` varchar(64) DEFAULT '' COMMENT '头像地址链接', 64 | PRIMARY KEY (`id`) 65 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 ; -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/resources/application-test-sofa.properties: -------------------------------------------------------------------------------- 1 | # mysql 驱动: h2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | # h2 内存数据库 库名: test 4 | spring.datasource.url=jdbc:h2:mem:test 5 | # 初始化数据表 6 | spring.datasource.schema=classpath:SofaDashboardDB.sql 7 | server.port=8086 8 | spring.application.name=test-backend 9 | 10 | # ark 管控端配置中心地址 11 | com.alipay.sofa.dashboard.zookeeper.address=127.0.0.1:2181 12 | # zookeeper 注册中心地址 13 | com.alipay.sofa.dashboard.registry=sofa://127.0.0.1:9603 -------------------------------------------------------------------------------- /sofa-dashboard-backend/sofa-dashboard-web/src/test/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | # mysql 驱动: h2 2 | spring.datasource.driver-class-name=org.h2.Driver 3 | # h2 内存数据库 库名: test 4 | spring.datasource.url=jdbc:h2:mem:test 5 | # 初始化数据表 6 | spring.datasource.schema=classpath:SofaDashboardDB.sql 7 | server.port=8086 8 | spring.application.name=test-backend 9 | 10 | # ark 管控端配置中心地址 11 | com.alipay.sofa.dashboard.zookeeper.address=127.0.0.1:2181 12 | # zookeeper 注册中心地址 13 | com.alipay.sofa.dashboard.registry=zookeeper://127.0.0.1:2181 -------------------------------------------------------------------------------- /sofa-dashboard-front/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "globals": { 8 | "Atomics": "readonly", 9 | "SharedArrayBuffer": "readonly" 10 | }, 11 | "parserOptions": { 12 | "ecmaFeatures": { 13 | "jsx": true 14 | }, 15 | "ecmaVersion": 2018, 16 | "sourceType": "module" 17 | }, 18 | "plugins": [ 19 | "react" 20 | ], 21 | "rules": { 22 | } 23 | }; -------------------------------------------------------------------------------- /sofa-dashboard-front/README.md: -------------------------------------------------------------------------------- 1 | # SOFA Dashboard 2 | 3 | ## Environment Prepare 4 | 5 | Install `node_modules`: 6 | 7 | ```bash 8 | npm install 9 | ``` 10 | 11 | or 12 | 13 | ```bash 14 | yarn 15 | ``` 16 | 17 | ## Start project 18 | 19 | ```bash 20 | npm run dev 21 | ``` 22 | 23 | ### Build project 24 | 25 | ```bash 26 | npm run build 27 | ``` 28 | -------------------------------------------------------------------------------- /sofa-dashboard-front/config/config.js: -------------------------------------------------------------------------------- 1 | import slash from 'slash'; 2 | import routes from './routes.config'; 3 | 4 | export default { 5 | devtool: 'source-map', 6 | hash: true, 7 | targets: { 8 | ie: 11, 9 | }, 10 | // umi routes: https://umijs.org/zh/guide/router.html 11 | routes: routes, 12 | // Theme for antd: https://ant.design/docs/react/customize-theme-cn 13 | theme: { 14 | 'primary-color': '#1890FF', 15 | }, 16 | proxy: { 17 | '/api': { 18 | target: 'http://localhost:8099/', 19 | changeOrigin: true, 20 | }, 21 | }, 22 | ignoreMomentLocale: true, 23 | lessLoaderOptions: { 24 | javascriptEnabled: true, 25 | }, 26 | disableRedirectHoist: true, 27 | cssLoaderOptions: { 28 | modules: true, 29 | getLocalIdent: (context, _, localName) => { 30 | if ( 31 | context.resourcePath.includes('node_modules') || 32 | context.resourcePath.includes('ant.design.pro.less') || 33 | context.resourcePath.includes('global.less') 34 | ) { 35 | return localName; 36 | } 37 | 38 | const match = context.resourcePath.match(/src(.*)/); 39 | 40 | if (match && match[1]) { 41 | const antdProPath = match[1].replace('.less', ''); 42 | const arr = slash(antdProPath) 43 | .split('/') 44 | .map(a => a.replace(/([A-Z])/g, '-$1')) 45 | .map(a => a.toLowerCase()); 46 | return `antd-pro${arr.join('-')}-${localName}`.replace(/--/g, '-'); 47 | } 48 | 49 | return localName; 50 | }, 51 | }, 52 | manifest: { 53 | basePath: '/', 54 | }, 55 | plugins: [ 56 | [ 57 | 'umi-plugin-react', 58 | { 59 | antd: true, 60 | dva: { 61 | hmr: true, 62 | }, 63 | }, 64 | ], 65 | [ 66 | 'umi-plugin-pro-block', 67 | { 68 | moveMock: false, 69 | moveService: false, 70 | modifyRequest: true, 71 | autoAddMenu: true, 72 | }, 73 | ], 74 | ], 75 | }; 76 | -------------------------------------------------------------------------------- /sofa-dashboard-front/config/routes.config.js: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | path: '/', 4 | component: '../layouts/BasicLayout', 5 | routes: [ 6 | { path: '/', redirect: '/dashboard/overview' }, 7 | { 8 | path: '/dashboard', 9 | name: '应用面板', 10 | icon: 'appstore', 11 | routes: [ 12 | { 13 | path: 'overview', 14 | name: '应用列表', 15 | component: 'Overview', 16 | }, 17 | { 18 | path: 'instance', 19 | name: '实例列表', 20 | component: 'Instance', 21 | }, 22 | { 23 | path: 'instance/*', 24 | component: './Instance/actuator', 25 | hideInMenu: true 26 | }, 27 | ] 28 | }, 29 | { 30 | path: '/governance', 31 | name: '服务治理', 32 | icon: 'appstore', 33 | routes: [ 34 | { 35 | path: 'governance', 36 | name: '服务列表', 37 | component: 'Governance', 38 | }, 39 | { 40 | path: 'details', 41 | component: './Governance/details', 42 | hideInMenu: true 43 | }, 44 | ] 45 | }, 46 | { 47 | path: '/ark', 48 | name: '动态模块', 49 | icon: 'appstore', 50 | routes: [ 51 | { 52 | path: 'ark', 53 | name: '模块列表', 54 | component: './Ark/index', 55 | }, 56 | { 57 | path: 'app', 58 | hideInMenu: true, 59 | component: './Ark/arkapp', 60 | }, 61 | ] 62 | }, 63 | // { 64 | // path: '/demo-page', 65 | // name: 'DemoPage', 66 | // icon: 'build', 67 | // component: 'DemoPage', 68 | // routes: [ 69 | // { 70 | // path: 'p1', 71 | // name: 'p1', 72 | // component: 'DemoPage', 73 | // routes: [ 74 | // { 75 | // path: 'p2', 76 | // name: 'p2', 77 | // component: 'DemoPage', 78 | // }, 79 | // ] 80 | // }, 81 | // { 82 | // path: 'p3', 83 | // name: 'p3', 84 | // component: 'DemoPage', 85 | // } 86 | // ] 87 | // }, 88 | 89 | // 登录注册页面,不展示在菜单侧边栏 90 | { 91 | path: '/login', 92 | exact: true, 93 | component: 'Login', 94 | }, 95 | 96 | ], 97 | } 98 | ]; 99 | -------------------------------------------------------------------------------- /sofa-dashboard-front/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "baseUrl": ".", 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /sofa-dashboard-front/mock/user.js: -------------------------------------------------------------------------------- 1 | export default { 2 | 'GET /api/user': { 3 | name: 'Serati Ma', 4 | avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png', 5 | userid: '00000001', 6 | email: 'antdesign@alipay.com', 7 | signature: '海纳百川,有容乃大', 8 | title: '交互专家', 9 | group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /sofa-dashboard-front/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sofa-dashboard", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "umi dev", 7 | "build": "umi build", 8 | "analyze": "cross-env ANALYZE=1 umi build", 9 | "lint": "eslint --fix --cache --ext .js,.jsx,.ts,.tsx --format=pretty ./src" 10 | }, 11 | "browserslist": [ 12 | "> 1%", 13 | "last 2 versions", 14 | "not ie <= 10" 15 | ], 16 | "dependencies": { 17 | "@ant-design/pro-layout": "4.5.10", 18 | "@antv/data-set": "^0.10.2", 19 | "ant-design-pro": "^2.3.2", 20 | "antd": "^3.20.0", 21 | "bizcharts": "^3.5.5", 22 | "classnames": "^2.2.6", 23 | "dva": "^2.4.1", 24 | "lodash": "^4.17.11", 25 | "memoize-one": "^5.0.4", 26 | "moment": "^2.24.0", 27 | "path-to-regexp": "^3.0.0", 28 | "prop-types": "^15.7.2", 29 | "qs": "^6.7.0", 30 | "react": "^16.8.6", 31 | "react-document-title": "^2.0.3", 32 | "react-dom": "^16.8.6", 33 | "react-json-view": "^1.19.1", 34 | "redux": "^4.0.1", 35 | "umi": "^2.8.8", 36 | "umi-plugin-pro-block": "^1.3.2", 37 | "umi-plugin-react": "^1.9.7", 38 | "umi-request": "^1.0.8" 39 | }, 40 | "devDependencies": { 41 | "@umijs/fabric": "^1.1.7", 42 | "cross-env": "^5.2.0", 43 | "eslint": "^6.0.1", 44 | "slash": "^3.0.0", 45 | "umi-plugin-pro": "^1.0.2", 46 | "webpack-theme-color-replacer": "^1.2.15" 47 | }, 48 | "engines": { 49 | "node": ">=10.0.0" 50 | } 51 | } -------------------------------------------------------------------------------- /sofa-dashboard-front/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | sofa-dashboard 7 | com.alipay.sofa 8 | 1.0.0-SNAPSHOT 9 | 10 | 11 | 4.0.0 12 | sofa-dashboard-front 13 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/layouts/BasicLayout.jsx: -------------------------------------------------------------------------------- 1 | import 'ant-design-pro/dist/ant-design-pro.css'; 2 | import React, { useState } from 'react'; 3 | import Link from 'umi/link'; 4 | import Redirect from 'umi/redirect'; 5 | import { connect } from 'dva'; 6 | import ProLayout from '@ant-design/pro-layout'; 7 | import { Typography } from 'antd'; 8 | 9 | const menuItemRender = (menuItemProps, defaultDom) => ( 10 | {defaultDom} 11 | ); 12 | 13 | const rightContentRender = () => { 14 | const style = { 15 | float: 'right', 16 | margin: '0 24px', 17 | }; 18 | return ( 19 |
20 | Ma Yun 21 |
22 | ); 23 | }; 24 | 25 | const footerRender = () => { 26 | const style = { 27 | margin: '2em 0', 28 | textAlign: 'center', 29 | }; 30 | return ( 31 | 34 | SOFA Stack 35 | 36 | ); 37 | }; 38 | 39 | const IndexLayout = props => { 40 | const { children, location, user } = props; 41 | const [collapsed, setCollapsed] = useState(false); 42 | 43 | if (location.pathname === '/login') { 44 | return children; 45 | } 46 | 47 | if (!user.userid) { 48 | return ; 49 | } 50 | 51 | return ( 52 | setCollapsed(status)} 59 | menuItemRender={menuItemRender} 60 | rightContentRender={rightContentRender} 61 | footerRender={footerRender} 62 | {...props}> 63 | {children} 64 | 65 | ); 66 | }; 67 | 68 | export default connect(({ user }) => ({ 69 | user, 70 | }))(IndexLayout); 71 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/application.js: -------------------------------------------------------------------------------- 1 | import { queryApplicationByKeyword } from '../services/application'; 2 | 3 | const ApplicationModel = { 4 | namespace: 'application', 5 | state: { 6 | list: [], 7 | }, 8 | reducers: { 9 | restate (state, action) { 10 | return { 11 | ...state, 12 | list: action.payload 13 | } 14 | }, 15 | }, 16 | effects: { 17 | * fetch ({ payload }, { call, put }) { 18 | const response = yield call(queryApplicationByKeyword, payload.applicationName); 19 | yield put({ 20 | type: 'restate', 21 | payload: response, 22 | }); 23 | }, 24 | }, 25 | }; 26 | 27 | export default ApplicationModel; 28 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/ark.js: -------------------------------------------------------------------------------- 1 | import { searchPlugins, queryAll, registerPlugin, updatePlugin, deletePlugin, relatedApp, cancelRelatedApp, submitVersion,deleteVersion } from '../services/ark'; 2 | 3 | const ArkModel = { 4 | namespace: 'ark', 5 | state: { 6 | list: [], 7 | }, 8 | reducers: { 9 | restate(state, action) { 10 | return { 11 | ...state, 12 | list: action.payload 13 | } 14 | }, 15 | }, 16 | effects: { 17 | // 获取所有插件 18 | *fetchPlugins({ payload }, { call, put }) { 19 | const response = yield call(queryAll, payload); 20 | yield put({ 21 | type: 'restate', 22 | payload: response, 23 | }); 24 | }, 25 | 26 | // 查询插件 27 | *searchPlugins({ payload }, { call, put }) { 28 | const response = yield call(searchPlugins, payload); 29 | yield put({ 30 | type: 'restate', 31 | payload: response, 32 | }); 33 | }, 34 | // 注册插件 35 | *pluginRegister({ payload }, { call, put }) { 36 | const result = yield call(registerPlugin, payload); 37 | 38 | if (result) { 39 | const response = yield call(queryAll, payload); 40 | yield put({ 41 | type: 'restate', 42 | payload: response, 43 | }); 44 | } 45 | 46 | return result; 47 | }, 48 | 49 | // 注册插件 50 | *updatePlugin({ payload }, { call, put }) { 51 | const result = yield call(updatePlugin, payload); 52 | if (result) { 53 | const response = yield call(queryAll, payload); 54 | yield put({ 55 | type: 'restate', 56 | payload: response, 57 | }); 58 | } 59 | return result; 60 | }, 61 | 62 | // 删除插件 63 | *deletePlugin({ payload }, { call, put }) { 64 | const result = yield call(deletePlugin, payload); 65 | if (result) { 66 | const response = yield call(queryAll, payload); 67 | yield put({ 68 | type: 'restate', 69 | payload: response, 70 | }); 71 | } 72 | return result; 73 | }, 74 | 75 | // 关联应用 76 | *relatedApp({ payload }, { call, put }) { 77 | const result = yield call(relatedApp, payload); 78 | if (result) { 79 | const response = yield call(queryAll, payload); 80 | yield put({ 81 | type: 'restate', 82 | payload: response, 83 | }); 84 | } 85 | return result; 86 | }, 87 | 88 | // 取消关联 89 | *cancelRelatedApp({ payload }, { call, put }) { 90 | const result = yield call(cancelRelatedApp, payload); 91 | if (result) { 92 | const response = yield call(queryAll, payload); 93 | yield put({ 94 | type: 'restate', 95 | payload: response, 96 | }); 97 | } 98 | return result; 99 | }, 100 | 101 | *submitVersion({ payload }, { call, put }) { 102 | const result = yield call(submitVersion, payload); 103 | if (result) { 104 | const response = yield call(queryAll, payload); 105 | yield put({ 106 | type: 'restate', 107 | payload: response, 108 | }); 109 | } 110 | return result; 111 | }, 112 | 113 | *deleteVersion({ payload }, { call, put }) { 114 | const result = yield call(deleteVersion, payload); 115 | if (result) { 116 | const response = yield call(queryAll, payload); 117 | yield put({ 118 | type: 'restate', 119 | payload: response, 120 | }); 121 | } 122 | return result; 123 | }, 124 | }, 125 | }; 126 | 127 | export default ArkModel; 128 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/arkapp.js: -------------------------------------------------------------------------------- 1 | import { queryArkAppList, queryBizState, pushCommand, getBizState } from '../services/arkapp'; 2 | 3 | const ArkAppModel = { 4 | namespace: 'arkapp', 5 | state: { 6 | ipUnitList: [], 7 | defaultVersion: "", 8 | versionList: [], 9 | bizState: {}, 10 | bizInfos: {} 11 | }, 12 | reducers: { 13 | restate(state, action) { 14 | return { 15 | ...state, 16 | ipUnitList: action.payload.ipUnitList, 17 | defaultVersion: action.payload.defaultVersion, 18 | versionList: action.payload.versionList, 19 | } 20 | }, 21 | 22 | setBizState(state, action) { 23 | return { 24 | ...state, 25 | bizState: action.payload, 26 | } 27 | }, 28 | }, 29 | 30 | effects: { 31 | // 获取所有宿主实例 32 | *fetchArkApps({ payload }, { call, put }) { 33 | const response = yield call(queryArkAppList, payload); 34 | yield put({ 35 | type: 'restate', 36 | payload: response, 37 | }); 38 | }, 39 | 40 | *fetchBizState({ payload }, { call, put }) { 41 | const response = yield call(queryBizState, payload); 42 | yield put({ 43 | type: 'setBizState', 44 | payload: response, 45 | }); 46 | }, 47 | 48 | // 推送命令 49 | *command({ payload }, { call }) { 50 | const response = yield call(pushCommand, payload); 51 | return response; 52 | }, 53 | 54 | 55 | // 推送命令 56 | *getBizState({ payload }, { call }) { 57 | const response = yield call(getBizState, payload); 58 | return response; 59 | }, 60 | }, 61 | }; 62 | 63 | export default ArkAppModel; 64 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/governance.js: -------------------------------------------------------------------------------- 1 | import { queryAll, queryServiceByAppName, queryProviderDetails, queryConsumerDetails } from '../services/governance'; 2 | 3 | const GovernanceModel = { 4 | namespace: 'governance', 5 | state: { 6 | list: [], 7 | providerListData: [], 8 | consumerListData: [], 9 | providerDetail: [], 10 | consumerDetail: [] 11 | }, 12 | reducers: { 13 | restate(state, action) { 14 | return { 15 | ...state, 16 | list: action.payload 17 | } 18 | }, 19 | 20 | restateForDrawer(state, action) { 21 | return { 22 | ...state, 23 | providerListData: action.payload.providers, 24 | consumerListData: action.payload.consumers 25 | } 26 | }, 27 | 28 | restateForProviderDetails(state, action) { 29 | return { 30 | ...state, 31 | providerDetail: action.payload, 32 | } 33 | }, 34 | 35 | restateForConsumerDetails(state, action) { 36 | return { 37 | ...state, 38 | consumerDetail: action.payload, 39 | } 40 | }, 41 | }, 42 | effects: { 43 | *fetch({ payload }, { call, put }) { 44 | const response = yield call(queryAll, payload); 45 | yield put({ 46 | type: 'restate', 47 | payload: response, 48 | }); 49 | }, 50 | 51 | *fetchServiceByMatch({ payload }, { call, put }) { 52 | const response = yield call(fetchServiceByMatch, payload); 53 | yield put({ 54 | type: 'restate', 55 | payload: response, 56 | }); 57 | }, 58 | 59 | *fetchServiceByAppName({ payload }, { call, put }) { 60 | const response = yield call(queryServiceByAppName, payload); 61 | yield put({ 62 | type: 'restateForDrawer', 63 | payload: response, 64 | }); 65 | }, 66 | 67 | 68 | *fetchProviderDetails({ payload }, { call, put }) { 69 | const response = yield call(queryProviderDetails, payload); 70 | yield put({ 71 | type: 'restateForProviderDetails', 72 | payload: response, 73 | }); 74 | }, 75 | 76 | *fetchConsumerDetails({ payload }, { call, put }) { 77 | const response = yield call(queryConsumerDetails, payload); 78 | yield put({ 79 | type: 'restateForConsumerDetails', 80 | payload: response, 81 | }); 82 | }, 83 | }, 84 | }; 85 | 86 | export default GovernanceModel; 87 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/instance.js: -------------------------------------------------------------------------------- 1 | import { queryInstance } from '../services/application'; 2 | 3 | const IntsnaceModel = { 4 | namespace: 'instance', 5 | state: { 6 | list: [], 7 | }, 8 | reducers: { 9 | restate(state, action) { 10 | return { 11 | ...state, 12 | list: action.payload 13 | } 14 | }, 15 | }, 16 | effects: { 17 | *fetch({ payload }, { call, put }) { 18 | const response = yield call(queryInstance, payload); 19 | yield put({ 20 | type: 'restate', 21 | payload: response, 22 | }); 23 | }, 24 | }, 25 | }; 26 | 27 | export default IntsnaceModel; 28 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/monitor.js: -------------------------------------------------------------------------------- 1 | import { 2 | queryInstanceEnv, 3 | queryInstanceHealth, 4 | queryInstanceInfo, 5 | queryInstanceLoggers, 6 | queryInstanceMappings, 7 | queryMemoryInfo, 8 | queryThreadInfo, 9 | } from '../services/application'; 10 | 11 | const MonitorModel = { 12 | namespace: 'monitor', 13 | state: { 14 | env: {}, 15 | health: {}, 16 | mappings: {}, 17 | loggers: {}, 18 | info: {}, 19 | thread: [], 20 | memory: [], 21 | }, 22 | reducers: { 23 | loadEnv (state, action) { 24 | return { 25 | ...state, 26 | env: action.payload 27 | } 28 | }, 29 | loadHealth (state, action) { 30 | return { 31 | ...state, 32 | health: action.payload 33 | } 34 | }, 35 | loadMappings (state, action) { 36 | return { 37 | ...state, 38 | mappings: action.payload 39 | } 40 | }, 41 | loadLoggers (state, action) { 42 | return { 43 | ...state, 44 | loggers: action.payload 45 | } 46 | }, 47 | loadInfo (state, action) { 48 | return { 49 | ...state, 50 | info: action.payload 51 | } 52 | }, 53 | loadThread (state, action) { 54 | return { 55 | ...state, 56 | thread: action.payload 57 | } 58 | }, 59 | loadMemory (state, action) { 60 | return { 61 | ...state, 62 | memory: action.payload 63 | } 64 | } 65 | }, 66 | effects: { 67 | * fetchEnv ({ payload }, { call, put }) { 68 | const response = yield call(queryInstanceEnv, payload.instanceId); 69 | yield put({ 70 | type: 'loadEnv', 71 | payload: response 72 | }) 73 | }, 74 | * fetchHealth ({ payload }, { call, put }) { 75 | const response = yield call(queryInstanceHealth, payload.instanceId); 76 | yield put({ 77 | type: 'loadHealth', 78 | payload: response 79 | }) 80 | }, 81 | * fetchMappings ({ payload }, { call, put }) { 82 | const response = yield call(queryInstanceMappings, payload.instanceId); 83 | yield put({ 84 | type: 'loadMappings', 85 | payload: response 86 | }) 87 | }, 88 | * fetchLoggers ({ payload }, { call, put }) { 89 | const response = yield call(queryInstanceLoggers, payload.instanceId); 90 | yield put({ 91 | type: 'loadLoggers', 92 | payload: response 93 | }) 94 | }, 95 | * fetchInfo ({ payload }, { call, put }) { 96 | const response = yield call(queryInstanceInfo, payload.instanceId); 97 | yield put({ 98 | type: 'loadInfo', 99 | payload: response 100 | }) 101 | }, 102 | * fetchThread ({ payload }, { call, put }) { 103 | const response = yield call(queryThreadInfo, payload.instanceId); 104 | yield put({ 105 | type: 'loadThread', 106 | payload: response 107 | }) 108 | }, 109 | * fetchMemory ({ payload }, { call, put }) { 110 | const response = yield call(queryMemoryInfo, payload.instanceId); 111 | yield put({ 112 | type: 'loadMemory', 113 | payload: response 114 | }) 115 | }, 116 | }, 117 | }; 118 | 119 | export default MonitorModel; 120 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/models/user.js: -------------------------------------------------------------------------------- 1 | import { queryUser } from '../services/user'; 2 | 3 | const UserModel = { 4 | namespace: 'user', 5 | state: { 6 | userid: '123', 7 | }, 8 | reducers: { 9 | restate: (state, action) => ({ ...state, ...action.payload }), 10 | }, 11 | effects: { 12 | *fetchUser(_, { call, put }) { 13 | const response = yield call(queryUser); 14 | yield put({ 15 | type: 'restate', 16 | payload: response, 17 | }); 18 | }, 19 | }, 20 | }; 21 | 22 | export default UserModel; 23 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Ark/RegisterPluginFrom.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Card, Table, Divider, Input, Tag, Modal, Button, Select, Form, Radio, Tooltip } from 'antd'; 3 | // eslint-disable-next-line 4 | class RegisterPluginFrom extends React.Component { 5 | render() { 6 | const { visible, onCancel, onCreate, form, confirmLoading, arkModalData } = this.props; 7 | const { getFieldDecorator } = form; 8 | return ( 9 | 17 |
18 | {/* 隐藏域,用于更新时导出插件id */} 19 | 20 | {getFieldDecorator('id', { 21 | initialValue: arkModalData.id || '', 22 | })()} 23 | 24 | 25 | {getFieldDecorator('pluginName', { 26 | initialValue: arkModalData.pluginName || '', 27 | rules: [{ required: true, message: 'Please input the plugin name!' }], 28 | })()} 29 | 30 | 31 | {getFieldDecorator('description', { 32 | initialValue: arkModalData.description || '', 33 | rules: [{ required: false, message: 'Please input the plugin name!' }], 34 | })()} 35 | 36 |
37 |
38 | ); 39 | } 40 | } 41 | export default Form.create({ name: 'form_in_modal_related_app' })(RegisterPluginFrom); -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Ark/RegisterVersionForm.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Input, Modal, Form } from 'antd'; 3 | 4 | class RegisterVersionForm extends React.Component { 5 | render() { 6 | const { visible, onCancel, onCreate, form, confirmLoading } = this.props; 7 | const { getFieldDecorator } = form; 8 | return ( 9 | 16 |
17 | 18 | {getFieldDecorator('version', { 19 | initialValue: '', 20 | rules: [{ required: true, message: 'Please input the module version!' }], 21 | })()} 22 | 23 | 24 | {getFieldDecorator('address', { 25 | initialValue: '', 26 | rules: [{ required: true, message: 'Please input the module file address!' }], 27 | })()} 28 | 29 |
30 |
31 | ); 32 | } 33 | } 34 | 35 | export default Form.create({ name: 'form_in_modal_register_version' })(RegisterVersionForm); 36 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Ark/RelatedAppForm.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Input, Modal, Form } from 'antd'; 3 | 4 | class RelatedAppForm extends React.Component { 5 | render() { 6 | const { visible, onCancel, onCreate, form, confirmLoading } = this.props; 7 | const { getFieldDecorator } = form; 8 | return ( 9 | 16 |
17 | 18 | {getFieldDecorator('appName', { 19 | initialValue: '', 20 | rules: [{ required: true, message: 'Please input the app name!' }], 21 | })()} 22 | 23 |
24 |
25 | ); 26 | } 27 | } 28 | 29 | export default Form.create({ name: 'form_in_modal_related_app' })(RelatedAppForm); 30 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/DemoPage/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Result, Icon } from 'antd'; 3 | 4 | export default function (props) { 5 | return ( 6 | } 8 | title={`当前页面路径是 ${props.location.pathname}`} 9 | /> 10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Governance/details.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Card, Table, Input, Select, Drawer, List ,Tabs} from 'antd'; 3 | import { connect } from 'dva'; 4 | const { Option } = Select; 5 | const { Search } = Input; 6 | const { TabPane } = Tabs; 7 | @connect(({ governance }) => ({ 8 | providerDetail: governance.providerDetail, 9 | consumerDetail: governance.consumerDetail 10 | })) 11 | class ServiceDetails extends React.Component { 12 | 13 | componentDidMount() { 14 | const { dispatch, location } = this.props; 15 | const queryParams = location.query; 16 | const serviceId = queryParams.serviceId + location.hash 17 | dispatch({ 18 | type: 'governance/fetchProviderDetails', 19 | payload: { 20 | "dataid":serviceId, 21 | } 22 | }); 23 | } 24 | 25 | render() { 26 | const {dispatch, location } = this.props; 27 | const queryParams = location.query; 28 | const serviceId = queryParams.serviceId + location.hash 29 | function callback(key) { 30 | // 1: 请求服务提供方数据 31 | if (key == 1) { 32 | dispatch({ 33 | type: 'governance/fetchProviderDetails', 34 | payload: { 35 | "dataid":serviceId, 36 | } 37 | }); 38 | } 39 | // 2: 请求服务消费方数据 40 | if (key == 2) { 41 | dispatch({ 42 | type: 'governance/fetchConsumerDetails', 43 | payload: { 44 | "dataid":serviceId, 45 | } 46 | }); 47 | } 48 | } 49 | 50 | // 服务提供方列表表头 51 | const columnsProvider = [ 52 | { 53 | title: 'IP', 54 | dataIndex: 'address', 55 | key: 'address', 56 | }, 57 | { 58 | title: '端口', 59 | dataIndex: 'port', 60 | key: 'port', 61 | }, 62 | { 63 | title: '权重', 64 | dataIndex: 'weight', 65 | key: 'weight', 66 | }, 67 | { 68 | title: '应用', 69 | dataIndex: 'appName', 70 | key: 'appName', 71 | }, 72 | ]; 73 | 74 | // 服务消费者列表表头 75 | const columnsConsumer = [ 76 | { 77 | title: 'IP', 78 | dataIndex: 'address', 79 | key: 'address', 80 | }, 81 | { 82 | title: '端口', 83 | dataIndex: 'port', 84 | key: 'port', 85 | }, 86 | { 87 | title: '应用', 88 | dataIndex: 'appName', 89 | key: 'appName', 90 | }, 91 | ]; 92 | 93 | return ( 94 |
95 | 96 | 服务ID : {serviceId} 97 | 98 | 99 | 100 | 101 | record.address} 105 | /> 106 | 107 | 108 |
record.address} 112 | /> 113 | 114 | 115 | 116 | 117 | ); 118 | } 119 | }; 120 | 121 | export default ServiceDetails; -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/actuator.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Card, Tabs} from 'antd'; 3 | import {connect} from 'dva'; 4 | import OverView from './tab/overview' 5 | import Environment from "./tab/environment"; 6 | import Loggers from "./tab/loggers"; 7 | import Mappings from './tab/mappings'; 8 | 9 | const {TabPane} = Tabs; 10 | 11 | @connect(({instance}) => ({ 12 | list: instance.list, 13 | })) 14 | class Actuator extends React.Component { 15 | state = { 16 | activeKey: '1', 17 | }; 18 | 19 | componentDidMount() { 20 | } 21 | 22 | changeTab = (key) => { 23 | this.setState({activeKey: key}); 24 | }; 25 | 26 | render() { 27 | const {activeKey} = this.state; 28 | 29 | return ( 30 | 31 | 32 | 33 | { 34 | activeKey === '1' 35 | && 36 | 37 | } 38 | 39 | 40 | { 41 | activeKey === '2' 42 | && 43 | 44 | } 45 | 46 | 47 | { 48 | activeKey === '3' 49 | && 50 | 51 | } 52 | 53 | 54 | { 55 | activeKey === '4' 56 | && 57 | 58 | } 59 | 60 | 61 | 62 | ); 63 | } 64 | }; 65 | export default Actuator; 66 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/component/MetricsGraph.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Card } from 'antd'; 3 | import DataSet from "@antv/data-set"; 4 | import { Axis, Chart, Geom, Legend, Tooltip, } from "bizcharts"; 5 | 6 | class MetricsGraph extends React.Component { 7 | 8 | render() { 9 | const { DataView } = DataSet; 10 | const dv = new DataView().source(this.props.data); 11 | dv.transform({ 12 | type: "percent", 13 | field: "value", 14 | dimension: "timestamp", 15 | groupBy: ["name"], 16 | as: "percent" 17 | }); 18 | return ( 19 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | ); 38 | } 39 | } 40 | 41 | export default MetricsGraph; 42 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/component/PropertyDetail.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styles from '../monitor.less'; 3 | import { Card } from "antd"; 4 | import ReactJson from 'react-json-view' 5 | 6 | /** 7 | * 用于展示属性详情的弹窗 8 | */ 9 | class PropertyDetail extends React.Component { 10 | 11 | convertToList(data, ref, prefix) { 12 | if (ref === undefined || data === undefined) { 13 | ref = [] 14 | } 15 | const thisPrefix = prefix === undefined ? "" : prefix; 16 | if (data === undefined) { 17 | // Do nothing 18 | } else if (data.children === undefined) { 19 | ref.push({ 20 | "name": data.name, 21 | "value": data.value, 22 | prefix: thisPrefix 23 | }) 24 | } else { 25 | for (const child of data.children) { 26 | const nextPrefix = thisPrefix.length === 0 ? data.name : thisPrefix + ' > ' + data.name; 27 | this.convertToList(child, ref, nextPrefix) 28 | } 29 | } 30 | return ref 31 | } 32 | 33 | render() { 34 | const list = this.convertToList(this.props.data); 35 | console.log("this.props.data", this.props.data); 36 | return ( 37 | 38 | 45 | {/* { 46 | 47 | {this.renderTreeNodes(item.children)} 48 | 49 | // list.map(item => { 50 | // return ( 51 | //
52 | // {item.prefix + item.name}
53 | // 54 | // {item.value === "" ? "" : item.value} 55 | // 56 | //
57 | // ); 58 | // }) 59 | } */} 60 |
61 | ); 62 | } 63 | 64 | } 65 | 66 | export default PropertyDetail; 67 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/component/PropsMonitor.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import {Card} from 'antd'; 3 | import styles from '../monitor.less'; 4 | 5 | /** 6 | * 应用属性变量相关展示组件 7 | */ 8 | class PropsMonitor extends React.Component { 9 | 10 | render() { 11 | const hasData = this.props.data['overview'] !== undefined 12 | && this.props.data['overview'].length > 0; 13 | return ( 14 | 16 |
17 |
18 | { 19 | //展示由接口生成的 overview 信息 20 | hasData ? this.props.data['overview'].map(item => { 21 | return ( 22 |
23 | {this.trimText(item.key, 40)} 24 | {item.value} 29 |
30 | ) 31 | }) : (

No data

) 32 | } 33 |
34 |
35 |
36 | ) 37 | } 38 | 39 | trimText(origin, limit) { 40 | return origin.length > limit ? origin.substring(0, limit) + "..." : origin; 41 | } 42 | } 43 | 44 | export default PropsMonitor; 45 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Card, Input, Table, Tag } from 'antd'; 3 | import { connect } from 'dva'; 4 | 5 | const { Search } = Input; 6 | 7 | @connect(({ instance }) => ({ 8 | list: instance.list, 9 | })) 10 | class Instance extends React.Component { 11 | 12 | componentDidMount () { 13 | const { location } = this.props; 14 | const queryParams = location.query; 15 | this.getData(queryParams.applicationName); 16 | } 17 | 18 | getData = (keyWord) => { 19 | const { dispatch } = this.props; 20 | dispatch({ 21 | type: 'instance/fetch', 22 | payload: { 23 | "applicationName": keyWord || '' 24 | } 25 | }); 26 | } 27 | 28 | handleSearch = (value) => { 29 | this.getData(value); 30 | } 31 | 32 | parseDate = (str) => { 33 | function addZero (num) { 34 | if (parseInt(num) < 10) { 35 | num = '0' + num; 36 | } 37 | return num; 38 | } 39 | 40 | const oDate = new Date(str), 41 | oYear = oDate.getFullYear(), 42 | oMonth = oDate.getMonth() + 1, 43 | oDay = oDate.getDate(), 44 | oHour = oDate.getHours(), 45 | oMin = oDate.getMinutes(), 46 | oSen = oDate.getSeconds(), 47 | oTime = oYear + '-' + addZero(oMonth) + '-' + addZero(oDay) + ' ' + addZero(oHour) + ':' + 48 | addZero(oMin) + ':' + addZero(oSen); 49 | return oTime; 50 | } 51 | 52 | render () { 53 | const columns = [ 54 | { 55 | title: '应用名', 56 | dataIndex: 'appName', 57 | key: 'appName', 58 | }, 59 | { 60 | title: 'IP', 61 | dataIndex: 'hostName', 62 | key: 'hostName', 63 | }, 64 | { 65 | title: '内部IP', 66 | dataIndex: 'internalHost', 67 | key: 'internalHost', 68 | }, 69 | { 70 | title: '端口', 71 | dataIndex: 'port', 72 | key: 'port', 73 | }, 74 | { 75 | title: '状态', 76 | dataIndex: 'appState', 77 | key: 'appState', 78 | render: appState => ( 79 | 80 | { 81 | 82 | { appState } 83 | 84 | } 85 | 86 | ), 87 | }, 88 | { 89 | title: '启动时间', 90 | key: 'startTime', 91 | render: (text, record) => ( 92 | 93 | { this.parseDate(record.startTime) } 94 | 95 | ) 96 | }, 97 | { 98 | title: '上次恢复', 99 | key: 'lastRecover', 100 | render: (text, record) => ( 101 | 102 | { this.parseDate(record.lastRecover) } 103 | 104 | ) 105 | }, 106 | { 107 | title: '操作', 108 | key: 'action', 109 | render: (text, record) => ( 110 | 111 | 状态查看 112 | 113 | ), 114 | }, 115 | ]; 116 | return ( 117 | 118 | this.handleSearch(value) } 119 | enterButton style={ { width: 500, marginBottom: 20 } }/> 120 |
record.hostName } 124 | /> 125 | 126 | ); 127 | } 128 | }; 129 | 130 | export default Instance; 131 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/monitor.less: -------------------------------------------------------------------------------- 1 | @import '~antd/lib/style/themes/default.less'; 2 | 3 | .text-right { 4 | float: right; 5 | } 6 | 7 | .item-info { 8 | padding: 6px 12px 6px 12px; 9 | border-bottom: 1px dashed #ebedf0; 10 | align-content: baseline; 11 | } 12 | 13 | .item-info:hover { 14 | background: #f0f0f0; 15 | } 16 | 17 | .item-info-span-title { 18 | display: inline-block; 19 | font-size: 0.8em; 20 | } 21 | 22 | .item-info-span-content { 23 | font-size: 1.1em; 24 | margin-left: 1em; 25 | color: limegreen; 26 | } 27 | 28 | .item-info .tooltips { 29 | // visibility: hidden; 30 | background-color: black; 31 | color: #fff; 32 | text-align: center; 33 | border-radius: 6px; 34 | padding: 6px; 35 | 36 | position: fixed; 37 | z-index: 10; 38 | left: 63%; 39 | top: 5%; 40 | } 41 | 42 | // .item-info:hover .tooltips { 43 | // visibility: visible; 44 | // } 45 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/tab/environment.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "dva"; 3 | import PropsMonitor from '../component/PropsMonitor'; 4 | import PropertyDetail from "../component/PropertyDetail"; 5 | 6 | /** 7 | * 应用信息展示控制台 8 | */ 9 | @connect(({ monitor }) => ({ 10 | monitor: monitor, 11 | })) 12 | class Environment extends React.Component { 13 | 14 | componentDidMount() { 15 | this.load('fetchEnv'); 16 | 17 | const intervalId = setInterval(() => { 18 | this.load('fetchEnv'); 19 | 20 | }, 5000); 21 | this.setState({ intervalId: intervalId }) 22 | } 23 | 24 | componentWillUnmount() { 25 | // use intervalId from the state to clear the interval 26 | clearInterval(this.state.intervalId); 27 | } 28 | 29 | render() { 30 | return ( 31 |
32 | {/* */} 38 | 41 |
42 | ) 43 | }; 44 | 45 | load = (type) => { 46 | const { dispatch } = this.props; 47 | dispatch({ 48 | type: 'monitor/' + type, 49 | payload: { 50 | instanceId: this.props.id 51 | } 52 | }) 53 | }; 54 | } 55 | 56 | 57 | export default Environment; 58 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/tab/loggers.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import {connect} from "dva"; 3 | import PropsMonitor from '../component/PropsMonitor'; 4 | import PropertyDetail from "../component/PropertyDetail"; 5 | 6 | /** 7 | * 应用信息展示控制台 8 | */ 9 | @connect(({monitor}) => ({ 10 | monitor: monitor, 11 | })) 12 | class Loggers extends React.Component { 13 | 14 | componentDidMount() { 15 | this.load('fetchLoggers'); 16 | 17 | const intervalId = setInterval(() => { 18 | this.load('fetchLoggers'); 19 | 20 | }, 5000); 21 | this.setState({intervalId: intervalId}) 22 | } 23 | 24 | componentWillUnmount() { 25 | // use intervalId from the state to clear the interval 26 | clearInterval(this.state.intervalId); 27 | } 28 | 29 | render() { 30 | return ( 31 |
32 | 35 |
36 | ) 37 | }; 38 | 39 | load = (type) => { 40 | const {dispatch} = this.props; 41 | dispatch({ 42 | type: 'monitor/' + type, 43 | payload: { 44 | instanceId: this.props.id 45 | } 46 | }) 47 | }; 48 | } 49 | 50 | 51 | export default Loggers; 52 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Instance/tab/mappings.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { connect } from "dva"; 3 | import PropsMonitor from '../component/PropsMonitor'; 4 | import PropertyDetail from "../component/PropertyDetail"; 5 | 6 | /** 7 | * 应用信息展示控制台 8 | */ 9 | @connect(({ monitor }) => ({ 10 | monitor: monitor, 11 | })) 12 | class Mappings extends React.Component { 13 | 14 | componentDidMount() { 15 | this.load('fetchMappings'); 16 | 17 | const intervalId = setInterval(() => { 18 | this.load('fetchMappings'); 19 | 20 | }, 5000); 21 | this.setState({ intervalId: intervalId }) 22 | } 23 | 24 | componentWillUnmount() { 25 | // use intervalId from the state to clear the interval 26 | clearInterval(this.state.intervalId); 27 | } 28 | 29 | render() { 30 | return ( 31 |
32 | 35 |
36 | ) 37 | }; 38 | 39 | load = (type) => { 40 | const { dispatch } = this.props; 41 | dispatch({ 42 | type: 'monitor/' + type, 43 | payload: { 44 | instanceId: this.props.id 45 | } 46 | }) 47 | }; 48 | } 49 | 50 | 51 | export default Mappings; 52 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Login/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Redirect from 'umi/redirect'; 3 | import { Form, Icon, Input, Button } from 'antd'; 4 | import { connect } from 'dva'; 5 | import Styles from './index.less'; 6 | 7 | class NormalLoginForm extends React.Component { 8 | handleSubmit = e => { 9 | e.preventDefault(); 10 | this.props.form.validateFields((err, values) => { 11 | if (!err) { 12 | // 发送用户信息,这里的 values 现在并没有使用 13 | this.props.dispatch({ 14 | type: 'user/fetchUser', 15 | payload: values, 16 | }); 17 | } 18 | }); 19 | }; 20 | 21 | render() { 22 | const { form, user } = this.props; 23 | const { getFieldDecorator } = form; 24 | 25 | if (user.userid) { 26 | return ; 27 | } 28 | 29 | return ( 30 |
31 |
32 | 33 | {getFieldDecorator('username', { 34 | rules: [{ required: true, message: 'Please input your username!' }], 35 | })( 36 | } 38 | placeholder="Username" 39 | />, 40 | )} 41 | 42 | 43 | {getFieldDecorator('password', { 44 | rules: [{ required: true, message: 'Please input your Password!' }], 45 | })( 46 | } 48 | type="password" 49 | placeholder="Password" 50 | />, 51 | )} 52 | 53 | 56 | 57 |
58 | ); 59 | } 60 | } 61 | 62 | const WrappedNormalLoginForm = Form.create({ name: 'normal_login' })(NormalLoginForm); 63 | 64 | export default connect(({ user }) => ({ 65 | user, 66 | }))(WrappedNormalLoginForm); 67 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Login/index.less: -------------------------------------------------------------------------------- 1 | .login { 2 | display: flex; 3 | justify-content: center; 4 | align-items: center; 5 | width: 100vw; 6 | height: 100vh; 7 | 8 | :global { 9 | .login-form { 10 | width: 300px; 11 | } 12 | .login-form-forgot { 13 | float: right; 14 | } 15 | .login-form-button { 16 | width: 100%; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/pages/Overview/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Card, Table, Divider, Input } from 'antd'; 3 | import { connect } from 'dva'; 4 | const { Search } = Input; 5 | @connect(({ application }) => ({ 6 | list: application.list || [], 7 | })) 8 | class Overview extends React.Component { 9 | 10 | getData = (keyWord) => { 11 | const { dispatch } = this.props; 12 | dispatch({ 13 | type: 'application/fetch', 14 | payload: { 15 | "applicationName": keyWord 16 | } 17 | }); 18 | } 19 | 20 | componentDidMount() { 21 | this.getData(""); 22 | } 23 | 24 | handleSearch = (value) => { 25 | this.getData(value); 26 | } 27 | render() { 28 | const columns = [ 29 | { 30 | title: '应用名', 31 | dataIndex: 'applicationName', 32 | key: 'applicationName', 33 | }, 34 | { 35 | title: '应用实例数', 36 | dataIndex: 'applicationCount', 37 | key: 'applicationCount', 38 | }, 39 | { 40 | title: '操作', 41 | key: 'action', 42 | render: (text, record) => ( 43 | 44 | 实例列表 45 | 46 | 配置 47 | 48 | ), 49 | }, 50 | ]; 51 | 52 | return ( 53 | 54 | this.handleSearch(value)} enterButton style={{ width: 500, marginBottom: 20 }} /> 55 | 56 | {this.props.list && ( 57 |
record.applicationName} 61 | /> 62 | )} 63 | 64 | ); 65 | } 66 | }; 67 | 68 | export default Overview; -------------------------------------------------------------------------------- /sofa-dashboard-front/src/services/application.js: -------------------------------------------------------------------------------- 1 | import { stringify } from 'qs'; 2 | import request from '../utils/request'; 3 | 4 | export async function queryApplicationByKeyword (keyword) { 5 | return request(`/api/application?keyword=${keyword}`); 6 | } 7 | 8 | export async function queryInstance (params) { 9 | return request(`/api/instance?${ stringify(params) }`); 10 | } 11 | 12 | export async function queryInstanceEnv (instanceId) { 13 | return request(`/api/instance/${ instanceId }/env`); 14 | } 15 | 16 | export async function queryInstanceHealth (instanceId) { 17 | return request(`/api/instance/${ instanceId }/health`); 18 | } 19 | 20 | export async function queryInstanceLoggers (instanceId) { 21 | return request(`/api/instance/${ instanceId }/loggers`); 22 | } 23 | 24 | export async function queryInstanceMappings (instanceId) { 25 | return request(`/api/instance/${ instanceId }/mappings`); 26 | } 27 | 28 | export async function queryInstanceInfo (instanceId) { 29 | return request(`/api/instance/${ instanceId }/info`); 30 | } 31 | 32 | export async function queryThreadInfo (instanceId) { 33 | return request(`/api/instance/${ instanceId }/thread`) 34 | } 35 | 36 | export async function queryMemoryInfo (instanceId) { 37 | return request(`/api/instance/${ instanceId }/memory`) 38 | } 39 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/services/ark.js: -------------------------------------------------------------------------------- 1 | import { stringify } from 'qs'; 2 | import request from '../utils/request'; 3 | 4 | export async function queryAll(params) { 5 | return request(`/api/ark/plugin-list?${stringify(params)}`); 6 | } 7 | 8 | export async function searchPlugins(params) { 9 | return request(`/api/ark/search-plugin?${stringify(params)}`); 10 | } 11 | 12 | export async function registerPlugin(params) { 13 | return request('/api/ark/register', { 14 | method: 'POST', 15 | // 制定下 content-type ,否则会出现 415 16 | headers: { 'content-type': 'application/json' }, 17 | body: JSON.stringify(params), 18 | }); 19 | } 20 | 21 | export async function updatePlugin(params) { 22 | return request('/api/ark/update-plugin', { 23 | method: 'POST', 24 | // 制定下 content-type ,否则会出现 415 25 | headers: { 'content-type': 'application/json' }, 26 | body: JSON.stringify(params), 27 | }); 28 | } 29 | 30 | export async function deletePlugin(params) { 31 | return request(`/api/ark/delete-plugin?${stringify(params)}`); 32 | } 33 | 34 | export async function relatedApp(params) { 35 | return request(`/api/ark/related-app?${stringify(params)}`); 36 | } 37 | 38 | export async function cancelRelatedApp(params) { 39 | return request(`/api/ark/cancel-related-app?${stringify(params)}`); 40 | } 41 | 42 | export async function submitVersion(params) { 43 | return request('/api/ark/register-new-version', { 44 | method: 'POST', 45 | // 制定下 content-type ,否则会出现 415 46 | headers: { 'content-type': 'application/json' }, 47 | body: JSON.stringify(params), 48 | }); 49 | } 50 | export async function deleteVersion(params) { 51 | return request(`/api/ark/delete-version?${stringify(params)}`); 52 | } 53 | 54 | 55 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/services/arkapp.js: -------------------------------------------------------------------------------- 1 | import { stringify } from 'qs'; 2 | import request from '../utils/request'; 3 | 4 | export async function queryArkAppList(params) { 5 | return request(`/api/arkapp/ark-app?${stringify(params)}`); 6 | } 7 | 8 | export async function queryBizState(params) { 9 | return request(`/api/arkapp/biz-state-detail?${stringify(params)}`); 10 | } 11 | 12 | export async function getBizState(params) { 13 | return request(`/api/arkapp/biz-state?${stringify(params)}`); 14 | } 15 | 16 | // 推送命令 17 | export async function pushCommand(params) { 18 | return request('/api/arkapp/command', { 19 | method: 'POST', 20 | headers: { 'content-type': 'application/json' }, 21 | body: JSON.stringify(params), 22 | }); 23 | } -------------------------------------------------------------------------------- /sofa-dashboard-front/src/services/governance.js: -------------------------------------------------------------------------------- 1 | import { stringify } from 'qs'; 2 | import request from '../utils/request'; 3 | 4 | export async function queryAll(params) { 5 | if (params.queryType === 'app') { 6 | return request(`/api/service/all-app?query=` + params.queryKey); 7 | } else { 8 | return request(`/api/service/all-service?query=` + params.queryKey); 9 | } 10 | } 11 | 12 | export async function queryServiceByAppName(params) { 13 | return request(`/api/service/service-app?${stringify(params)}`); 14 | } 15 | 16 | // 获取服务发布详情 17 | export async function queryProviderDetails(params) { 18 | return request(`/api/service/query/providers?${stringify(params)}`); 19 | } 20 | 21 | // 获取服务消费详情 22 | export async function queryConsumerDetails(params) { 23 | return request(`/api/service/query/consumers?${stringify(params)}`); 24 | } -------------------------------------------------------------------------------- /sofa-dashboard-front/src/services/user.js: -------------------------------------------------------------------------------- 1 | import request from '../utils/request'; 2 | 3 | export async function queryUser() { 4 | return request('/api/user'); 5 | } 6 | -------------------------------------------------------------------------------- /sofa-dashboard-front/src/utils/request.js: -------------------------------------------------------------------------------- 1 | /** 2 | * request 网络请求工具 3 | * 更详细的 api 文档: https://github.com/umijs/umi-request 4 | */ 5 | import { extend } from 'umi-request'; 6 | import { notification } from 'antd'; 7 | 8 | const codeMessage = { 9 | 200: '服务器成功返回请求的数据。', 10 | 201: '新建或修改数据成功。', 11 | 202: '一个请求已经进入后台排队(异步任务)。', 12 | 204: '删除数据成功。', 13 | 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。', 14 | 401: '用户没有权限(令牌、用户名、密码错误)。', 15 | 403: '用户得到授权,但是访问是被禁止的。', 16 | 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。', 17 | 406: '请求的格式不可得。', 18 | 410: '请求的资源被永久删除,且不会再得到的。', 19 | 422: '当创建一个对象时,发生一个验证错误。', 20 | 500: '服务器发生错误,请检查服务器。', 21 | 502: '网关错误。', 22 | 503: '服务不可用,服务器暂时过载或维护。', 23 | 504: '网关超时。', 24 | }; 25 | /** 26 | * 异常处理程序 27 | */ 28 | 29 | const errorHandler = error => { 30 | const { response } = error; 31 | 32 | if (response && response.status) { 33 | const errorText = codeMessage[response.status] || response.statusText; 34 | const { status, url } = response; 35 | notification.error({ 36 | message: `请求错误 ${status}: ${url}`, 37 | description: errorText, 38 | }); 39 | } 40 | }; 41 | /** 42 | * 配置request请求时的默认参数 43 | */ 44 | 45 | const request = extend({ 46 | errorHandler, 47 | // 默认错误处理 48 | credentials: 'include', // 默认请求是否带上cookie 49 | }); 50 | export default request; 51 | -------------------------------------------------------------------------------- /sql/SofaDashboardDB.sql: -------------------------------------------------------------------------------- 1 | -- ---------------------------- 2 | -- Create Database 3 | -- ---------------------------- 4 | CREATE DATABASE IF NOT EXISTS SofaDashboardDB DEFAULT CHARACTER SET = utf8mb4; 5 | Use SofaDashboardDB; 6 | 7 | -- ---------------------------- 8 | -- Table structure for ark_module_app 9 | -- ---------------------------- 10 | DROP TABLE IF EXISTS `ark_module_app`; 11 | CREATE TABLE `ark_module_app` ( 12 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块应用主键', 13 | `module_id` int(11) NOT NULL COMMENT '模块id', 14 | `app_name` varchar(128) NOT NULL COMMENT '应用名', 15 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '模块创建时间', 16 | PRIMARY KEY (`id`) 17 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT '模块-应用关联表'; 18 | 19 | -- ---------------------------- 20 | -- Table structure for ark_module_info 21 | -- ---------------------------- 22 | DROP TABLE IF EXISTS `ark_module_info`; 23 | CREATE TABLE `ark_module_info` ( 24 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块主键', 25 | `plugin_name` varchar(128) NOT NULL COMMENT '模块名', 26 | `description` varchar(128) DEFAULT '' COMMENT '模块描述', 27 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '模块创建时间', 28 | PRIMARY KEY (`id`) 29 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT '模块信息表'; 30 | 31 | -- ---------------------------- 32 | -- Table structure for ark_module_user 33 | -- ---------------------------- 34 | DROP TABLE IF EXISTS `ark_module_user`; 35 | CREATE TABLE `ark_module_user` ( 36 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块负责人表主键', 37 | `module_id` int(11) NOT NULL COMMENT '插件模块id', 38 | `user_id` int(11) DEFAULT NULL COMMENT '插件ownerId', 39 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 40 | PRIMARY KEY (`id`) 41 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT '模块-负责人表'; 42 | 43 | -- ---------------------------- 44 | -- Table structure for ark_module_version 45 | -- ---------------------------- 46 | DROP TABLE IF EXISTS `ark_module_version`; 47 | CREATE TABLE `ark_module_version` ( 48 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '模块版本表主键', 49 | `module_id` int(11) NOT NULL COMMENT '模块id', 50 | `module_version` varchar(64) NOT NULL COMMENT '模块版本', 51 | `source_path` varchar(1024) DEFAULT '' COMMENT '资源路径', 52 | `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 53 | `is_release` tinyint(4) DEFAULT 0 COMMENT '是否发布', 54 | PRIMARY KEY (`id`) 55 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT '模块-版本表'; 56 | 57 | -- ---------------------------- 58 | -- Table structure for sofa_dashboard_user 59 | -- ---------------------------- 60 | DROP TABLE IF EXISTS `sofa_dashboard_user`; 61 | CREATE TABLE `sofa_dashboard_user` ( 62 | `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户表id', 63 | `nick_name` varchar(64) DEFAULT '' COMMENT '昵称', 64 | `email` varchar(64) DEFAULT '' COMMENT '用户邮箱', 65 | `phone` varchar(12) DEFAULT '' COMMENT '用户电话', 66 | `password` varchar(32) DEFAULT '' COMMENT '用户密码', 67 | `header_img_url` varchar(64) DEFAULT '' COMMENT '头像地址链接', 68 | PRIMARY KEY (`id`) 69 | ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COMMENT '用户表'; 70 | 71 | -------------------------------------------------------------------------------- /tools/change_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | shellDir=$(cd "$(dirname "$0")"; pwd) 3 | 4 | shopt -s expand_aliases 5 | if [ ! -n "$1" ] ;then 6 | echo "Please enter a version" 7 | exit 1 8 | else 9 | echo "The version is $1 !" 10 | fi 11 | 12 | if [ `uname` == "Darwin" ] ;then 13 | echo "This is OS X" 14 | alias sed='sed -i ""' 15 | else 16 | echo "This is Linux" 17 | alias sed='sed -i' 18 | fi 19 | 20 | cd $shellDir/.. 21 | echo "Change version in registry-parent ===>" 22 | sed "// s/[^\$].*<\/version>/$1<\/version>/" ./pom.xml 23 | 24 | echo "Change version in registry-client-all ===>" 25 | sed "/[^\$].*<\/version>/$1<\/version>/" ./client/all/pom.xml 26 | 27 | echo "Change version in subproject pom ===>" 28 | for filename in `find . -name "pom.xml" -maxdepth 4`;do 29 | if [ $filename == "./client/all/pom.xml" ]; then 30 | continue 31 | fi 32 | echo "Deal with $filename" 33 | sed "//,/<\/parent>/ s/[^\$].*<\/version>/$1<\/version>/" $filename 34 | done 35 | 36 | #TODO 37 | #echo "Change version in server shell ===>" -------------------------------------------------------------------------------- /tools/check_format.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | BASEDIR=$(dirname $0) 4 | 5 | cd ${BASEDIR} 6 | 7 | # make sure git has no un commit files 8 | if [ -n "$(git status --untracked-files=no --porcelain)" ]; then 9 | echo "Please commit your change before run this shell, un commit files:" 10 | git status --untracked-files=no --porcelain 11 | exit 1 12 | fi -------------------------------------------------------------------------------- /tools/codestyle/HEADER: -------------------------------------------------------------------------------- 1 | Licensed to the Apache Software Foundation (ASF) under one or more 2 | contributor license agreements. See the NOTICE file distributed with 3 | this work for additional information regarding copyright ownership. 4 | The ASF licenses this file to You under the Apache License, Version 2.0 5 | (the "License"); you may not use this file except in compliance with 6 | the License. You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. --------------------------------------------------------------------------------