Browse Source

canal admin

mcy 5 years ago
parent
commit
483044916d
52 changed files with 339 additions and 32 deletions
  1. 7 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java
  2. 5 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java
  3. 4 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/CanalServerMXBean.java
  4. 3 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java
  5. 2 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/NodeServerService.java
  6. 23 0
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java
  7. 15 5
      canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java
  8. BIN
      canal-admin/canal-admin-server/src/main/resources/public/avatar.gif
  9. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/index.html
  10. BIN
      canal-admin/canal-admin-server/src/main/resources/public/logo.png
  11. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/app.bb951cb3.css
  12. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-101fc062.fad9926f.css
  13. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-238a81e9.e8e2beee.css
  14. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-2ead9580.da8fbef7.css
  15. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-37c49cbf.efc21a9c.css
  16. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-555c32e2.9d3c5014.css
  17. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-63c8061b.acff1abf.css
  18. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-666608b4.fd6bfc93.css
  19. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-69386cf0.741ff14e.css
  20. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-7279d7fc.84a25dbe.css
  21. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-elementUI.18b11d0e.css
  22. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-libs.5cf311f0.css
  23. BIN
      canal-admin/canal-admin-server/src/main/resources/public/static/fonts/element-icons.2fad952a.woff
  24. BIN
      canal-admin/canal-admin-server/src/main/resources/public/static/fonts/element-icons.6f0a7632.ttf
  25. BIN
      canal-admin/canal-admin-server/src/main/resources/public/static/img/404.a57b6f31.png
  26. BIN
      canal-admin/canal-admin-server/src/main/resources/public/static/img/404_cloud.0f4bc32b.png
  27. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/app.1b0a659b.js
  28. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-101fc062.bc898027.js
  29. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-238a81e9.273bda76.js
  30. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-2ead9580.e145af54.js
  31. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-37c49cbf.64d26540.js
  32. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-3fcdf643.4b7133b8.js
  33. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-555c32e2.c9d04b33.js
  34. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-57829aa9.389c1070.js
  35. 1 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-63c8061b.7ccc9231.js
  36. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-666608b4.1b76bd53.js
  37. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-69386cf0.76d77f5c.js
  38. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-7279d7fc.bcdb3ff5.js
  39. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.f532f91b.js
  40. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-elementUI.667f4c87.js
  41. 0 0
      canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-libs.c04beefc.js
  42. 8 1
      canal-admin/canal-admin-ui/src/api/canalInstance.js
  43. 7 0
      canal-admin/canal-admin-ui/src/api/nodeServer.js
  44. 14 0
      canal-admin/canal-admin-ui/src/router/index.js
  45. 53 0
      canal-admin/canal-admin-ui/src/views/canalServer/CanalInstanceLogDetail.vue
  46. 51 0
      canal-admin/canal-admin-ui/src/views/canalServer/CanalLogDetail.vue
  47. 10 2
      canal-admin/canal-admin-ui/src/views/canalServer/canalInstance.vue
  48. 4 0
      canal-admin/canal-admin-ui/src/views/canalServer/nodeServer.vue
  49. 83 0
      common/src/main/java/com/alibaba/otter/canal/common/utils/FileUtils.java
  50. 24 24
      deployer/src/main/bin/startup.bat
  51. 11 0
      deployer/src/main/java/com/alibaba/otter/canal/deployer/mbean/CanalServerBean.java
  52. 4 0
      deployer/src/main/java/com/alibaba/otter/canal/deployer/mbean/CanalServerMXBean.java

+ 7 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/CanalInstanceController.java

@@ -1,6 +1,7 @@
 package com.alibaba.otter.canal.admin.controller;
 
 import java.util.List;
+import java.util.Map;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -54,4 +55,10 @@ public class CanalInstanceController {
     public BaseModel<Boolean> stop(@PathVariable Long id, @PathVariable Long nodeId, @PathVariable String env) {
         return BaseModel.getInstance(canalInstanceConfigService.remoteOperation(id, nodeId, "stop"));
     }
+
+    @GetMapping(value = "/instance/log/{id}/{nodeId}")
+    public BaseModel<Map<String, String>> start(@PathVariable Long id, @PathVariable Long nodeId,
+                                                @PathVariable String env) {
+        return BaseModel.getInstance(canalInstanceConfigService.remoteInstanceLog(id, nodeId));
+    }
 }

+ 5 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/controller/NodeServerController.java

@@ -54,6 +54,11 @@ public class NodeServerController {
         return BaseModel.getInstance(nodeServerService.remoteOperation(id, "start"));
     }
 
+    @GetMapping(value = "/nodeServer/log/{id}")
+    public BaseModel<String> log(@PathVariable Long id, @PathVariable String env) {
+        return BaseModel.getInstance(nodeServerService.remoteCanalLog(id));
+    }
+
     @PutMapping(value = "/nodeServer/stop/{id}")
     public BaseModel<Boolean> stop(@PathVariable Long id, @PathVariable String env) {
         return BaseModel.getInstance(nodeServerService.remoteOperation(id, "stop"));

+ 4 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/jmx/CanalServerMXBean.java

@@ -19,4 +19,8 @@ public interface CanalServerMXBean {
     boolean reloadInstance(String destination);
 
     String getRunningInstances();
+
+    String canalLog();
+
+    String instanceLog(String destination);
 }

+ 3 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/CanalInstanceService.java

@@ -3,6 +3,7 @@ package com.alibaba.otter.canal.admin.service;
 import com.alibaba.otter.canal.admin.model.CanalInstanceConfig;
 
 import java.util.List;
+import java.util.Map;
 
 public interface CanalInstanceService {
 
@@ -16,5 +17,7 @@ public interface CanalInstanceService {
 
     void delete(Long id);
 
+    Map<String, String> remoteInstanceLog(Long id, Long nodeId);
+
     boolean remoteOperation(Long id, Long nodeId, String option);
 }

+ 2 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/NodeServerService.java

@@ -18,5 +18,7 @@ public interface NodeServerService {
 
     int remoteNodeStatus(String ip, Integer port);
 
+    String remoteCanalLog(Long id);
+
     boolean remoteOperation(Long id, String option);
 }

+ 23 - 0
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/CanalInstanceServiceImpl.java

@@ -1,6 +1,8 @@
 package com.alibaba.otter.canal.admin.service.impl;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
@@ -70,6 +72,27 @@ public class CanalInstanceServiceImpl implements CanalInstanceService {
         }
     }
 
+    public Map<String, String> remoteInstanceLog(Long id, Long nodeId) {
+        Map<String, String> result = new HashMap<>();
+
+        NodeServer nodeServer = NodeServer.find.byId(nodeId);
+        if (nodeServer == null) {
+            return result;
+        }
+        CanalInstanceConfig canalInstanceConfig = CanalInstanceConfig.find.byId(id);
+        if (canalInstanceConfig == null) {
+            return result;
+        }
+
+        String log = JMXConnection.execute(nodeServer.getIp(),
+            nodeServer.getPort(),
+            canalServerMXBean -> canalServerMXBean.instanceLog(canalInstanceConfig.getName()));
+
+        result.put("instance", canalInstanceConfig.getName());
+        result.put("log", log);
+        return result;
+    }
+
     public boolean remoteOperation(Long id, Long nodeId, String option) {
         NodeServer nodeServer = null;
         if ("start".equals(option)) {

+ 15 - 5
canal-admin/canal-admin-server/src/main/java/com/alibaba/otter/canal/admin/service/impl/NodeServerServiceImpl.java

@@ -2,17 +2,19 @@ package com.alibaba.otter.canal.admin.service.impl;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.*;
-import java.util.function.Function;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
-import com.alibaba.otter.canal.admin.common.exception.ServiceException;
-import com.alibaba.otter.canal.admin.jmx.CanalServerMXBean;
-import com.alibaba.otter.canal.admin.jmx.JMXConnection;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
+import com.alibaba.otter.canal.admin.common.exception.ServiceException;
+import com.alibaba.otter.canal.admin.jmx.CanalServerMXBean;
+import com.alibaba.otter.canal.admin.jmx.JMXConnection;
 import com.alibaba.otter.canal.admin.model.NodeServer;
 import com.alibaba.otter.canal.admin.service.NodeServerService;
 
@@ -107,6 +109,14 @@ public class NodeServerServiceImpl implements NodeServerService {
         return resutl;
     }
 
+    public String remoteCanalLog(Long id) {
+        NodeServer nodeServer = NodeServer.find.byId(id);
+        if (nodeServer == null) {
+            return "";
+        }
+        return JMXConnection.execute(nodeServer.getIp(), nodeServer.getPort(), CanalServerMXBean::canalLog);
+    }
+
     public boolean remoteOperation(Long id, String option) {
         NodeServer nodeServer = NodeServer.find.byId(id);
         if (nodeServer == null) {

BIN
canal-admin/canal-admin-server/src/main/resources/public/avatar.gif


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/index.html


BIN
canal-admin/canal-admin-server/src/main/resources/public/logo.png


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/app.bb951cb3.css


+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-101fc062.fad9926f.css

@@ -0,0 +1 @@
+@supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-31c14ebf]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-31c14ebf]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-31c14ebf]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-31c14ebf]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-31c14ebf]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-31c14ebf]{position:relative}.login-container .title-container .title[data-v-31c14ebf]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .show-pwd[data-v-31c14ebf]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}

File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-238a81e9.e8e2beee.css


+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-2ead9580.da8fbef7.css

@@ -0,0 +1 @@
+.line[data-v-50b472ce]{text-align:center}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-37c49cbf.efc21a9c.css

@@ -0,0 +1 @@
+.dashboard-container[data-v-42037c2b]{margin:30px}.dashboard-text[data-v-42037c2b]{font-size:30px;line-height:46px}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-555c32e2.9d3c5014.css

@@ -0,0 +1 @@
+.line[data-v-44b63e9d]{text-align:center}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-63c8061b.acff1abf.css

@@ -0,0 +1 @@
+.line[data-v-5feb688e]{text-align:center}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-666608b4.fd6bfc93.css

@@ -0,0 +1 @@
+.line[data-v-4058c64d]{text-align:center}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-69386cf0.741ff14e.css

@@ -0,0 +1 @@
+.line[data-v-756ebb70]{text-align:center}

+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-7279d7fc.84a25dbe.css

@@ -0,0 +1 @@
+.line[data-v-11496239]{text-align:center}

File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-elementUI.18b11d0e.css


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/css/chunk-libs.5cf311f0.css


BIN
canal-admin/canal-admin-server/src/main/resources/public/static/fonts/element-icons.2fad952a.woff


BIN
canal-admin/canal-admin-server/src/main/resources/public/static/fonts/element-icons.6f0a7632.ttf


BIN
canal-admin/canal-admin-server/src/main/resources/public/static/img/404.a57b6f31.png


BIN
canal-admin/canal-admin-server/src/main/resources/public/static/img/404_cloud.0f4bc32b.png


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/app.1b0a659b.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-101fc062.bc898027.js


+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-238a81e9.273bda76.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-238a81e9"],{"26fc":function(t,s,a){t.exports=a.p+"static/img/404_cloud.0f4bc32b.png"},"8cdb":function(t,s,a){"use strict";a.r(s);var e=function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"wscn-http404-container"},[a("div",{staticClass:"wscn-http404"},[t._m(0),t._v(" "),a("div",{staticClass:"bullshit"},[a("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._v(" "),t._m(1),t._v(" "),a("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),t._v(" "),a("div",{staticClass:"bullshit__info"},[t._v("Please check that the URL you entered is correct, or click the button below to return to the homepage.")]),t._v(" "),a("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("Back to home")])])])])},c=[function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"pic-404"},[e("img",{staticClass:"pic-404__parent",attrs:{src:a("a36b"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child left",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child mid",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child right",attrs:{src:a("26fc"),alt:"404"}})])},function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"bullshit__info"},[t._v("All rights reserved\n        "),a("a",{staticStyle:{color:"#20a0ff"},attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[t._v("wallstreetcn")])])}],i={name:"Page404",computed:{message:function(){return"The webmaster said that you can not enter this page..."}}},l=i,n=(a("97ef"),a("2877")),r=Object(n["a"])(l,e,c,!1,null,"c095f994",null);s["default"]=r.exports},"97ef":function(t,s,a){"use strict";var e=a("b51e"),c=a.n(e);c.a},a36b:function(t,s,a){t.exports=a.p+"static/img/404.a57b6f31.png"},b51e:function(t,s,a){}}]);

File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-2ead9580.e145af54.js


+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-37c49cbf.64d26540.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-37c49cbf"],{3671:function(t,e,n){"use strict";var a=n("afe4"),c=n.n(a);c.a},9406:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement;t._self._c;return t._m(0)},c=[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"dashboard-container"},[n("div",{staticClass:"dashboard-text"},[t._v(" ")])])}],s=n("db72"),r=n("2f62"),u={name:"Dashboard",computed:Object(s["a"])({},Object(r["b"])(["name"])),mounted:function(){this.$router.push("/canalServer")}},i=u,o=(n("3671"),n("2877")),d=Object(o["a"])(i,a,c,!1,null,"42037c2b",null);e["default"]=d.exports},afe4:function(t,e,n){}}]);

File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-3fcdf643.4b7133b8.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-555c32e2.c9d04b33.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-57829aa9.389c1070.js


+ 1 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-63c8061b.7ccc9231.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-63c8061b"],{"09a8":function(n,t,e){"use strict";e.r(t);var o=function(){var n=this,t=n.$createElement,e=n._self._c||t;return e("div",[e("el-form",{ref:"form",attrs:{model:n.form}},[e("div",{staticStyle:{"padding-left":"10px","padding-top":"20px"}},[e("el-form-item",[n._v("\n        "+n._s(n.form.name)+"    \n        "),e("el-button",{attrs:{type:"primary"},on:{click:n.onSubmit}},[n._v("修改")]),n._v(" "),e("el-button",{attrs:{type:"warning"},on:{click:n.onCancel}},[n._v("重置")])],1)],1),n._v(" "),e("editor",{attrs:{lang:"properties",theme:"chrome",width:"100%",height:800},on:{init:n.editorInit},model:{value:n.form.content,callback:function(t){n.$set(n.form,"content",t)},expression:"form.content"}})],1)],1)},a=[],i=(e("7f7f"),e("b775"));function r(){return Object(i["a"])({url:"/canal/config",method:"get"})}function c(n){return Object(i["a"])({url:"/canal/config",method:"put",data:n})}var f={components:{editor:e("7c9e")},data:function(){return{form:{id:null,name:"",content:""}}},created:function(){this.loadCanalConfig()},methods:{editorInit:function(){e("2099"),e("be9d"),e("2968"),e("e0e5"),e("bb36"),e("0329"),e("95b8"),e("6a21")},loadCanalConfig:function(){var n=this;r().then(function(t){var e=t.data;n.form.id=e.id,n.form.name=e.name,n.form.content=e.content})},onSubmit:function(){var n=this;this.$confirm("修改Canal主配置可能会导致Server重启,是否继续?","确定修改",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}).then(function(){c(n.form).then(function(t){"success"===t.data?(n.$message({message:"修改成功",type:"success"}),n.loadCanalConfig()):n.$message({message:"修改失败",type:"error"})})})},onCancel:function(){this.loadCanalConfig()}}},s=f,u=(e("a447"),e("2877")),l=Object(u["a"])(s,o,a,!1,null,"5feb688e",null);t["default"]=l.exports},"70a0":function(n,t,e){},a447:function(n,t,e){"use strict";var o=e("70a0"),a=e.n(o);a.a}}]);

File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-666608b4.1b76bd53.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-69386cf0.76d77f5c.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-7279d7fc.bcdb3ff5.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-e1a839e4.f532f91b.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-elementUI.667f4c87.js


File diff suppressed because it is too large
+ 0 - 0
canal-admin/canal-admin-server/src/main/resources/public/static/js/chunk-libs.c04beefc.js


+ 8 - 1
canal-admin/canal-admin-ui/src/api/canalInstance.js

@@ -45,9 +45,16 @@ export function startInstance(id) {
   })
 }
 
-export function stopNodeServer(id, nodeId) {
+export function stopInstance(id, nodeId) {
   return request({
     url: '/canal/instance/stop/' + id + '/' + nodeId,
     method: 'put'
   })
 }
+
+export function instanceLog(id, nodeId) {
+  return request({
+    url: '/canal/instance/log/' + id + '/' + nodeId,
+    method: 'get'
+  })
+}

+ 7 - 0
canal-admin/canal-admin-ui/src/api/nodeServer.js

@@ -51,3 +51,10 @@ export function stopNodeServer(id) {
     method: 'put'
   })
 }
+
+export function nodeServerLog(id) {
+  return request({
+    url: '/nodeServer/log/' + id,
+    method: 'get'
+  })
+}

+ 14 - 0
canal-admin/canal-admin-ui/src/router/index.js

@@ -107,6 +107,20 @@ export const constantRoutes = [
         component: () => import('@/views/canalServer/CanalInstanceUpdate'),
         meta: { title: '修改实例配置' },
         hidden: true
+      },
+      {
+        path: 'nodeServer/log',
+        name: 'Canal日志',
+        component: () => import('@/views/canalServer/CanalLogDetail'),
+        meta: { title: 'Canal日志' },
+        hidden: true
+      },
+      {
+        path: 'canalInstance/log',
+        name: 'Canal Instance日志',
+        component: () => import('@/views/canalServer/CanalInstanceLogDetail'),
+        meta: { title: 'Canal Instance日志' },
+        hidden: true
       }
     ]
   },

+ 53 - 0
canal-admin/canal-admin-ui/src/views/canalServer/CanalInstanceLogDetail.vue

@@ -0,0 +1,53 @@
+<template>
+  <div>
+    <el-form ref="form" :model="form">
+      <div style="padding-left: 10px;padding-right: 10px;padding-top: 20px;">
+        <el-form-item>
+          {{ form.instance }}&nbsp;&nbsp;&nbsp;&nbsp;
+          <el-button type="primary" @click="onRefresh">刷新</el-button>
+          <el-button type="info" @click="onBack">返回</el-button>
+        </el-form-item>
+        <el-input v-model="form.desc" :rows="35" readonly="true" type="textarea" />
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { instanceLog } from '@/api/canalInstance'
+
+export default {
+  data() {
+    return {
+      form: {
+        instance: '',
+        desc: ''
+      }
+    }
+  },
+  created() {
+    this.fetchData()
+  },
+  methods: {
+    fetchData() {
+      instanceLog(this.$route.query.id, this.$route.query.nodeId).then(res => {
+        this.form.instance = res.data.instance + '.log'
+        this.form.desc = res.data.log
+      })
+    },
+    onRefresh() {
+      this.fetchData()
+    },
+    onBack() {
+      history.go(-1)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.line{
+  text-align: center;
+}
+</style>
+

+ 51 - 0
canal-admin/canal-admin-ui/src/views/canalServer/CanalLogDetail.vue

@@ -0,0 +1,51 @@
+<template>
+  <div>
+    <el-form ref="form" :model="form">
+      <div style="padding-left: 10px;padding-right: 10px;padding-top: 20px;">
+        <el-form-item>
+          canal.log&nbsp;&nbsp;&nbsp;&nbsp;
+          <el-button type="primary" @click="onRefresh">刷新</el-button>
+          <el-button type="info" @click="onBack">返回</el-button>
+        </el-form-item>
+        <el-input v-model="form.desc" :rows="35" readonly="true" type="textarea" />
+      </div>
+    </el-form>
+  </div>
+</template>
+
+<script>
+import { nodeServerLog } from '@/api/nodeServer'
+
+export default {
+  data() {
+    return {
+      form: {
+        desc: ''
+      }
+    }
+  },
+  created() {
+    this.fetchData()
+  },
+  methods: {
+    fetchData() {
+      nodeServerLog(this.$route.query.id).then(res => {
+        this.form.desc = res.data
+      })
+    },
+    onRefresh() {
+      this.fetchData()
+    },
+    onBack() {
+      history.go(-1)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.line{
+  text-align: center;
+}
+</style>
+

+ 10 - 2
canal-admin/canal-admin-ui/src/views/canalServer/canalInstance.vue

@@ -41,6 +41,7 @@
               <el-dropdown-item @click.native="handleDelete(scope.row)">删除实例</el-dropdown-item>
               <el-dropdown-item @click.native="handleStart(scope.row)">启动服务</el-dropdown-item>
               <el-dropdown-item @click.native="handleStop(scope.row)">停止服务</el-dropdown-item>
+              <el-dropdown-item @click.native="handleLog(scope.row)">日志详情</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
         </template>
@@ -50,7 +51,7 @@
 </template>
 
 <script>
-import { getCanalInstances, deleteCanalInstance, startInstance, stopNodeServer } from '@/api/canalInstance'
+import { getCanalInstances, deleteCanalInstance, startInstance, stopInstance } from '@/api/canalInstance'
 
 export default {
   filters: {
@@ -147,7 +148,7 @@ export default {
         cancelButtonText: '取消',
         type: 'warning'
       }).then(() => {
-        stopNodeServer(row.id, row.nodeId).then((res) => {
+        stopInstance(row.id, row.nodeId).then((res) => {
           if (res.data) {
             this.fetchData()
             this.$message({
@@ -162,6 +163,13 @@ export default {
           }
         })
       })
+    },
+    handleLog(row) {
+      if (row.nodeId === null) {
+        this.$message({ message: '当前实例不是启动状态,无法查看日志', type: 'warning' })
+        return
+      }
+      this.$router.push('canalInstance/log?id=' + row.id + '&nodeId=' + row.nodeId)
     }
   }
 }

+ 4 - 0
canal-admin/canal-admin-ui/src/views/canalServer/nodeServer.vue

@@ -51,6 +51,7 @@
               <el-dropdown-item @click.native="handleDelete(scope.row)">删除节点</el-dropdown-item>
               <el-dropdown-item @click.native="handleStart(scope.row)">启动服务</el-dropdown-item>
               <el-dropdown-item @click.native="handleStop(scope.row)">停止服务</el-dropdown-item>
+              <el-dropdown-item @click.native="handleLog(scope.row)">日志详情</el-dropdown-item>
             </el-dropdown-menu>
           </el-dropdown>
         </template>
@@ -290,6 +291,9 @@ export default {
           }
         })
       })
+    },
+    handleLog(row) {
+      this.$router.push('nodeServer/log?id=' + row.id)
     }
   }
 }

+ 83 - 0
common/src/main/java/com/alibaba/otter/canal/common/utils/FileUtils.java

@@ -0,0 +1,83 @@
+package com.alibaba.otter.canal.common.utils;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.charset.StandardCharsets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileUtils {
+
+    private static final Logger logger = LoggerFactory.getLogger(FileUtils.class);
+
+    public static String readFileFromOffset(String filename, int l, String charset) {
+        RandomAccessFile rf = null;
+        StringBuilder res = new StringBuilder();
+        try {
+            rf = new RandomAccessFile(filename, "r");
+
+            long fileLength = rf.length();
+
+            long start = rf.getFilePointer();
+
+            long readIndex = start + fileLength - 1;
+
+            String line;
+            rf.seek(readIndex);
+
+            int k = 0;
+            int c = -1;
+            while (readIndex > start) {
+                if (k == l) {
+                    break;
+                }
+                c = rf.read();
+                String readText = null;
+                if (c == '\n' || c == '\r') {
+                    line = rf.readLine();
+                    if (line != null) {
+                        readText = new String(line.getBytes(StandardCharsets.ISO_8859_1), charset);
+                    } else {
+                        if (k != 0) {
+                            res.insert(0, "\n");
+                        }
+                        res.insert(0, "");
+                        k++;
+                    }
+                    readIndex--;
+                }
+                readIndex--;
+                rf.seek(readIndex);
+                if (readIndex == 0) {
+                    readText = rf.readLine();
+                }
+                if (readText != null) {
+                    if (k != 0) {
+                        res.insert(0, "\n");
+                    }
+                    res.insert(0, readText);
+                    k++;
+                }
+            }
+        } catch (IOException e) {
+            logger.error(e.getMessage(), e);
+        } finally {
+            if (rf != null) {
+                try {
+                    rf.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+                rf = null;
+            }
+        }
+
+        return res.toString();
+    }
+
+    public static void main(String[] args) {
+        String res = readFileFromOffset("test2.txt", 2, "UTF-8");
+        System.out.println(res);
+    }
+}

+ 24 - 24
deployer/src/main/bin/startup.bat

@@ -1,25 +1,25 @@
-@echo off
-@if not "%ECHO%" == ""  echo %ECHO%
-@if "%OS%" == "Windows_NT"  setlocal
-
-set ENV_PATH=.\
-if "%OS%" == "Windows_NT" set ENV_PATH=%~dp0%
-
-set conf_dir=%ENV_PATH%\..\conf
-set canal_conf=%conf_dir%\canal.properties
-set logback_configurationFile=%conf_dir%\logback.xml
-
-set CLASSPATH=%conf_dir%
-set CLASSPATH=%conf_dir%\..\lib\*;%CLASSPATH%
-
-set JAVA_MEM_OPTS= -Xms128m -Xmx512m -XX:PermSize=128m
-set JAVA_OPTS_EXT= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8
-set JAVA_DEBUG_OPT= -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9099,server=y,suspend=n
-set CANAL_OPTS= -DappName=otter-canal -Dlogback.configurationFile="%logback_configurationFile%" -Dcanal.conf="%canal_conf%"
-
-set JAVA_OPTS= %JAVA_MEM_OPTS% %JAVA_OPTS_EXT% %JAVA_DEBUG_OPT% %CANAL_OPTS%
-
-set CMD_STR= java %JAVA_OPTS% -classpath "%CLASSPATH%" java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.deployer.CanalLauncher
-echo start cmd : %CMD_STR%
-
+@echo off
+@if not "%ECHO%" == ""  echo %ECHO%
+@if "%OS%" == "Windows_NT"  setlocal
+
+set ENV_PATH=.\
+if "%OS%" == "Windows_NT" set ENV_PATH=%~dp0%
+
+set conf_dir=%ENV_PATH%\..\conf
+set canal_conf=%conf_dir%\canal.properties
+set logback_configurationFile=%conf_dir%\logback.xml
+
+set CLASSPATH=%conf_dir%
+set CLASSPATH=%conf_dir%\..\lib\*;%CLASSPATH%
+
+set JAVA_MEM_OPTS= -Xms128m -Xmx512m -XX:PermSize=128m
+set JAVA_OPTS_EXT= -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dapplication.codeset=UTF-8 -Dfile.encoding=UTF-8
+set JAVA_DEBUG_OPT= -server -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=9099,server=y,suspend=n
+set CANAL_OPTS= -DappName=otter-canal -Dlogback.configurationFile="%logback_configurationFile%" -Dcanal.conf="%canal_conf%"
+
+set JAVA_OPTS= %JAVA_MEM_OPTS% %JAVA_OPTS_EXT% %JAVA_DEBUG_OPT% %CANAL_OPTS%
+
+set CMD_STR= java %JAVA_OPTS% -classpath "%CLASSPATH%" java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.deployer.CanalLauncher
+echo start cmd : %CMD_STR%
+
 java %JAVA_OPTS% -classpath "%CLASSPATH%" com.alibaba.otter.canal.deployer.CanalLauncher

+ 11 - 0
deployer/src/main/java/com/alibaba/otter/canal/deployer/mbean/CanalServerBean.java

@@ -1,5 +1,6 @@
 package com.alibaba.otter.canal.deployer.mbean;
 
+import com.alibaba.otter.canal.common.utils.FileUtils;
 import com.alibaba.otter.canal.deployer.CanalLauncher;
 import com.alibaba.otter.canal.deployer.CanalStater;
 import com.alibaba.otter.canal.deployer.InstanceConfig;
@@ -127,6 +128,16 @@ public class CanalServerBean extends NotificationBroadcasterSupport implements C
         return "";
     }
 
+    @Override
+    public String canalLog() {
+        return FileUtils.readFileFromOffset("../logs/canal/canal.log", 100, "UTF-8");
+    }
+
+    @Override
+    public String instanceLog(String destination) {
+        return FileUtils.readFileFromOffset("../logs/" + destination + "/" + destination + ".log", 100, "UTF-8");
+    }
+
     private InstanceAction getInstanceAction(String destination) {
         Map<InstanceConfig.InstanceMode, InstanceConfigMonitor> monitors = canalStater.getController()
             .getInstanceConfigMonitors();

+ 4 - 0
deployer/src/main/java/com/alibaba/otter/canal/deployer/mbean/CanalServerMXBean.java

@@ -19,4 +19,8 @@ public interface CanalServerMXBean {
     boolean reloadInstance(String destination);
 
     String getRunningInstances();
+
+    String canalLog();
+
+    String instanceLog(String destination);
 }

Some files were not shown because too many files changed in this diff