diff --git a/Makefile b/Makefile index ad5ac07..fff6b00 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,12 @@ windows_build: docker_build: linux_build docker build -t shiguanghuxian/etcd-manage . +docker_run: docker_build + docker-compose up --force-recreate + +docker_cluster_run: docker_build + docker-compose -f docker-compose-cluster.yml up --force-recreate + run: build @./bin/etcd-manage @@ -24,5 +30,6 @@ build_web: clean: @rm -f ./bin/etcd-manage* + @rm -f ./bin/logs/* .PHONY: default build linux_build windows_build clean \ No newline at end of file diff --git a/bin/config/cfg.toml b/bin/config/cfg.toml index ee048c2..b6bf771 100644 --- a/bin/config/cfg.toml +++ b/bin/config/cfg.toml @@ -13,15 +13,15 @@ port = 10280 ## 一下每一个server为一个etcd服务 ## [[server]] # 显示名称 -title = "测试环境" +title = "make docker_cluster_run" # 标识名 -name = "qa" +name = "docker_cluster_run" # etcd连接地址 如果为集群请填写全部地址 -address = ["127.0.0.1:2379"] +address = ["etcd0:2379","etcd1:2379","etcd2:2379"] # 查看的key前缀 key_prefix = "/root1" # 简述信息 -desc = "环境etcd" +desc = "docker方式etcd集群方式" # 可访问服务器角色列表 - 不写则为所有用户可访问 roles = ["admin"] # 是否启用tls连接 @@ -33,7 +33,15 @@ key_file = "key_file" ca_file = "ca_file" [[server]] -title = "本机" +title = "make docker_run" +name = "docker_run" +address = ["etcd:2379"] +key_prefix = "/" +desc = "docker方式etcd非集群方式" +roles = ["admin","dev"] + +[[server]] +title = "本地etcd" name = "local" address = ["127.0.0.1:2379"] key_prefix = "/" diff --git a/docker-compose-cluster.yml b/docker-compose-cluster.yml new file mode 100644 index 0000000..b057547 --- /dev/null +++ b/docker-compose-cluster.yml @@ -0,0 +1,83 @@ +version: '3' +services: + etcd0: + image: quay.io/coreos/etcd:v3.3 + ports: + - 2379 + volumes: + - etcd0:/etcd_data + command: + - /usr/local/bin/etcd + - -name + - etcd0 + - --data-dir + - /etcd_data + - -advertise-client-urls + - http://etcd0:2379 + - -listen-client-urls + - http://0.0.0.0:2379 + - -initial-advertise-peer-urls + - http://etcd0:2380 + - -listen-peer-urls + - http://0.0.0.0:2380 + - -initial-cluster + - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380 + etcd1: + image: quay.io/coreos/etcd:v3.3 + ports: + - 2379 + volumes: + - etcd1:/etcd_data + command: + - /usr/local/bin/etcd + - -name + - etcd1 + - --data-dir + - /etcd_data + - -advertise-client-urls + - http://etcd1:2379 + - -listen-client-urls + - http://0.0.0.0:2379 + - -initial-advertise-peer-urls + - http://etcd1:2380 + - -listen-peer-urls + - http://0.0.0.0:2380 + - -initial-cluster + - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380 + etcd2: + image: quay.io/coreos/etcd:v3.3 + ports: + - 2379 + volumes: + - etcd2:/etcd_data + command: + - /usr/local/bin/etcd + - -name + - etcd2 + - --data-dir + - /etcd_data + - -advertise-client-urls + - http://etcd2:2379 + - -listen-client-urls + - http://0.0.0.0:2379 + - -initial-advertise-peer-urls + - http://etcd2:2380 + - -listen-peer-urls + - http://0.0.0.0:2380 + - -initial-cluster + - etcd0=http://etcd0:2380,etcd1=http://etcd1:2380,etcd2=http://etcd2:2380 + etcd-manage: + # build: . + image: "shiguanghuxian/etcd-manage" + ports: + - "10280:10280" + volumes: + - ./bin/config/cfg.toml:/app/config/cfg.toml + - ./bin/logs:/app/logs + depends_on: + - etcd0 + +volumes: + etcd0: + etcd1: + etcd2: diff --git a/docker-compose.yml b/docker-compose.yml index b7f170b..7c022c8 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,6 +19,7 @@ services: image: "shiguanghuxian/etcd-manage" volumes: - ./bin/config/cfg.toml:/app/config/cfg.toml + - ./bin/logs:/app/logs ports: - "10280:10280" depends_on: diff --git a/program/logger/logger.go b/program/logger/logger.go index 9a95cd6..41d9966 100644 --- a/program/logger/logger.go +++ b/program/logger/logger.go @@ -18,18 +18,18 @@ var ( // InitLogger 日志初始化,用于记录操作日志 func InitLogger(logPath string, isDebug bool) (*zap.SugaredLogger, error) { infoLogPath := "" - errorLogPath := "" + // errorLogPath := "" if logPath == "" { logRoot := common.GetRootDir() + "logs/" if isExt, _ := common.PathExists(logRoot); isExt == false { os.MkdirAll(logRoot, os.ModePerm) } - infoLogPath = logRoot + time.Now().Format("20060102_info") + ".log" - errorLogPath = logRoot + time.Now().Format("20060102_error") + ".log" + infoLogPath = logRoot + time.Now().Format("20060102") + ".log" + // errorLogPath = logRoot + time.Now().Format("20060102_error") + ".log" } else { logPath = strings.TrimRight(logPath, string(os.PathSeparator)) - infoLogPath = logPath + string(os.PathSeparator) + time.Now().Format("20060102_info") + ".log" - errorLogPath = logPath + string(os.PathSeparator) + time.Now().Format("20060102_error") + ".log" + infoLogPath = logPath + string(os.PathSeparator) + time.Now().Format("20060102") + ".log" + // errorLogPath = logPath + string(os.PathSeparator) + time.Now().Format("20060102_error") + ".log" } cfg := &zap.Config{ @@ -40,11 +40,11 @@ func InitLogger(logPath string, isDebug bool) (*zap.SugaredLogger, error) { if isDebug == true { atom.SetLevel(zapcore.DebugLevel) cfg.OutputPaths = []string{"stdout"} - cfg.ErrorOutputPaths = []string{"stdout"} + // cfg.ErrorOutputPaths = []string{"stdout"} } else { atom.SetLevel(zapcore.InfoLevel) cfg.OutputPaths = []string{infoLogPath} - cfg.ErrorOutputPaths = []string{errorLogPath} + // cfg.ErrorOutputPaths = []string{errorLogPath} } cfg.Level = atom logger, err := cfg.Build() diff --git a/program/v1/v1.go b/program/v1/v1.go index 75d7a16..dd8dd4b 100644 --- a/program/v1/v1.go +++ b/program/v1/v1.go @@ -31,6 +31,8 @@ func V1(v1 *gin.RouterGroup) { v1.GET("/logs", getLogsList) // 查询日志 + v1.GET("/users", getUserList) // 获取用户列表 + v1.GET("/logtypes", getLogTypeList) // 获取日志类型列表 } // 获取etcd key列表 @@ -305,12 +307,41 @@ func getEtcdServerList(c *gin.Context) { c.JSON(http.StatusOK, list1) } +// 获取用户列表 +func getUserList(c *gin.Context) { + us := make([]map[string]string, 0) + cfg := config.GetCfg() + if cfg != nil { + for _, v := range cfg.Users { + us = append(us, map[string]string{ + "name": v.Username, + "role": v.Role, + }) + } + } + + c.JSON(http.StatusOK, us) +} + +// 获取操作类型列表 +func getLogTypeList(c *gin.Context) { + c.JSON(http.StatusOK, []string{ + "获取列表", + "获取key的值", + "获取etcd集群信息", + "删除key", + "保存key", + "获取etcd服务列表", + }) +} + type LogLine struct { - Date string `json:"date"` - User string `json:"user"` - Role string `json:"role"` - Msg string `json:"msg"` - Ts float64 `json:"ts"` + Date string `json:"date"` + User string `json:"user"` + Role string `json:"role"` + Msg string `json:"msg"` + Ts float64 `json:"ts"` + Level string `json:"level"` } // 查看日志 @@ -318,6 +349,8 @@ func getLogsList(c *gin.Context) { page := c.Query("page") pageSize := c.Query("page_size") dateStr := c.Query("date") + querUser := c.Query("user") + queryLogType := c.Query("log_type") var err error defer func() { @@ -341,7 +374,7 @@ func getLogsList(c *gin.Context) { startLine := (pageNum - 1) * pageSizeNum endLine := pageNum * pageSizeNum - fileName := fmt.Sprintf("%slogs/%s_info.log", common.GetRootDir(), dateStr) + fileName := fmt.Sprintf("%slogs/%s.log", common.GetRootDir(), dateStr) // fmt.Println(fileName) // 判断文件是否存在 if exists, err := common.PathExists(fileName); exists == false || err != nil { @@ -361,24 +394,38 @@ func getLogsList(c *gin.Context) { defer file.Close() fileScanner := bufio.NewScanner(file) lineCount := 1 - listStr := make([]string, 0) + list := make([]*LogLine, 0) // 最终数组 for fileScanner.Scan() { - if lineCount > startLine && lineCount <= endLine { - listStr = append(listStr, fileScanner.Text()) + logTxt := fileScanner.Text() + if logTxt == "" { + continue } - lineCount++ - } - // 解析每一行 - list := make([]*LogLine, 0) - for _, v := range listStr { + // 解析日志 oneLog := new(LogLine) - err = json.Unmarshal([]byte(v), oneLog) + err = json.Unmarshal([]byte(logTxt), oneLog) if err != nil { - logger.Log.Errorw("解析一行的日志错误", "err", err) + logger.Log.Errorw("解析日志文件错误", "err", err) + continue + } + // 只看info类型日志 + if oneLog.Level != "info" { continue } - oneLog.Date = time.Unix(int64(oneLog.Ts), 0).Format("2006-01-02 15:04:05") - list = append(list, oneLog) + + if lineCount > startLine && lineCount <= endLine { + // 判断用户和日志类型参数 + if querUser != "" && oneLog.User != querUser { + continue + } + if queryLogType != "" && oneLog.Msg != queryLogType { + continue + } + + oneLog.Date = time.Unix(int64(oneLog.Ts), 0).In(time.Local).Format("2006-01-02 15:04:05") + list = append(list, oneLog) + } + + lineCount++ } err = nil diff --git a/static/src/main.js b/static/src/main.js index e22e014..f23aa3b 100644 --- a/static/src/main.js +++ b/static/src/main.js @@ -25,7 +25,7 @@ Vue.use(VueCodemirror) Vue.config.productionTip = false; /* axios */ -axios.defaults.baseURL = 'http://127.0.0.1:10280'; +// axios.defaults.baseURL = 'http://127.0.0.1:10280'; // 请求拦截器 axios.interceptors.request.use(function (config) { diff --git a/static/src/views/Keys.vue b/static/src/views/Keys.vue index 2c9317e..145e9f3 100644 --- a/static/src/views/Keys.vue +++ b/static/src/views/Keys.vue @@ -40,7 +40,7 @@