├── .air.toml ├── .drone.yml ├── .gitignore ├── LICENSE ├── README.md ├── README.zh-CN.md ├── bee.json ├── cmd ├── init.go ├── install.go ├── uninstallaction.go ├── update.go ├── updateconf.go └── web.go ├── conf └── app.conf ├── control ├── controllers ├── ai.go ├── alarm.go ├── base.go ├── before.go ├── event_log.go ├── export.go ├── graph.go ├── group.go ├── history.go ├── histotry_graph.go ├── host.go ├── host_groups.go ├── images.go ├── index.go ├── item.go ├── problem.go ├── report.go ├── rule.go ├── system.go ├── task_log.go ├── template.go ├── topodata.go ├── topology.go ├── trend.go ├── trigger.go ├── user.go └── websocket.go ├── go.mod ├── go.sum ├── main.go ├── models ├── alarm.go ├── alarm_mod.go ├── application.go ├── application_mod.go ├── base.go ├── before.go ├── channel.go ├── chart_day.go ├── chart_week.go ├── config.go ├── cron.go ├── cron_init.go ├── cron_mail.go ├── cron_wechat.go ├── egress.go ├── event.go ├── export_table.go ├── export_table_mod.go ├── graph.go ├── graph_mod.go ├── group.go ├── history.go ├── history_mod.go ├── host.go ├── host_group.go ├── host_group_mod.go ├── host_mod.go ├── images.go ├── index.go ├── index_mod.go ├── inspect.go ├── item.go ├── item_mod.go ├── mail.go ├── menu.go ├── problem.go ├── report.go ├── report_mod.go ├── rule.go ├── rule_mod.go ├── session.go ├── system.go ├── system_mod.go ├── task_log.go ├── template.go ├── template_mod.go ├── topodata.go ├── topodata_mod.go ├── topology.go ├── topology_mod.go ├── trend.go ├── trend_mod.go ├── trigger.go ├── trigger_mod.go ├── user.go └── xlsx.go ├── nginx.conf ├── routers ├── commentsRouter_.go ├── commentsRouter_controllers.go └── router.go ├── template ├── mail_problem.tpl ├── mail_recovery.tpl ├── wechat_problem.tpl └── wechat_recovery.tpl ├── utils └── utils.go ├── zbxtable.init ├── zbxtable.png └── zbxtable.service /.air.toml: -------------------------------------------------------------------------------- 1 | root = "." 2 | testdata_dir = "testdata" 3 | tmp_dir = "tmp" 4 | 5 | [build] 6 | bin = "tmp\\main.exe web" 7 | cmd = "go build -o ./tmp/main.exe ." 8 | delay = 1000 9 | exclude_dir = ["assets", "tmp", "vendor", "testdata","download","web",".idea"] 10 | exclude_file = [] 11 | exclude_regex = ["_test.go"] 12 | exclude_unchanged = false 13 | follow_symlink = false 14 | full_bin = "" 15 | include_dir = [] 16 | include_ext = ["go", "tpl", "tmpl", "html"] 17 | kill_delay = "0s" 18 | log = "build-errors.log" 19 | send_interrupt = false 20 | stop_on_error = true 21 | 22 | [color] 23 | app = "" 24 | build = "yellow" 25 | main = "magenta" 26 | runner = "green" 27 | watcher = "cyan" 28 | 29 | [log] 30 | time = false 31 | 32 | [misc] 33 | clean_on_exit = false 34 | 35 | [screen] 36 | clear_on_rebuild = false 37 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: zbxtable 3 | steps: 4 | - name: build 5 | image: canhgia809/go:1.21.4-upx 6 | pull: if-not-exists 7 | commands: 8 | - wget -q -c https://dl.cactifans.com/stable/zbxtable/web-latest.tar.gz && tar xf web-latest.tar.gz 9 | - go install github.com/go-bindata/go-bindata/go-bindata@latest 10 | - chmod a+x ./control 11 | - ./control build 12 | - mv zbxtable zbxtable-${DRONE_COMMIT_SHA:0:10}-${DRONE_BUILD_NUMBER} 13 | - upx -9 -o zbxtable zbxtable-${DRONE_COMMIT_SHA:0:10}-${DRONE_BUILD_NUMBER} 14 | - ./control pack 15 | - name: scp dev 16 | image: appleboy/drone-scp 17 | settings: 18 | host: 19 | from_secret: 222_host 20 | port: 21 | from_secret: port 22 | username: 23 | from_secret: username 24 | password: 25 | from_secret: 222_password 26 | command_timeout: 10m 27 | target: 28 | - /home/wwwroot/downloads/dev 29 | source: 30 | - ./*.tar.gz 31 | when: 32 | branch: 33 | - dev 34 | - name: scp prod 35 | image: appleboy/drone-scp 36 | settings: 37 | host: 38 | from_secret: 222_host 39 | port: 40 | from_secret: port 41 | username: 42 | from_secret: username 43 | password: 44 | from_secret: 222_password 45 | command_timeout: 10m 46 | target: 47 | - /home/wwwroot/downloads/stable 48 | source: 49 | - ./*.tar.gz 50 | when: 51 | branch: 52 | - 2.1 53 | - name: scp demo 54 | image: appleboy/drone-scp 55 | settings: 56 | host: 57 | from_secret: demo_host 58 | port: 59 | from_secret: demo_port 60 | username: 61 | from_secret: demo_username 62 | password: 63 | from_secret: demo_password 64 | command_timeout: 10m 65 | target: 66 | - /tmp/zbxtable 67 | source: 68 | - zbxtable 69 | rm: true 70 | when: 71 | branch: 72 | - demo 73 | - name: ssh restart 74 | image: appleboy/drone-ssh 75 | settings: 76 | host: 77 | from_secret: demo_host 78 | username: 79 | from_secret: demo_username 80 | password: 81 | from_secret: demo_password 82 | port: 83 | from_secret: demo_port 84 | command_timeout: 10m 85 | script: 86 | - systemctl stop zbxtable 87 | - rm -rf /usr/local/zbxtable/zbxtable 88 | - mv /tmp/zbxtable/zbxtable /usr/local/zbxtable/ 89 | - systemctl start zbxtable 90 | when: 91 | branch: 92 | - demo -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lastupdate.tmp 2 | zbxtable 3 | zbxtable.exe 4 | zbxtable.exe~ 5 | */vendor 6 | .idea/ 7 | .DS_Store 8 | runtime/* 9 | *.DS_Store 10 | *.idea 11 | */.DS_Store 12 | */.idea 13 | */.vscode 14 | */bin 15 | *bin 16 | */test/* 17 | */test 18 | logs/* 19 | packfile/staticFile.go 20 | /web/ 21 | /zbxtable.exe 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | English | [简体中文](./README.zh-CN.md) 2 | 3 | # ZbxTable 4 | 5 | [![Build Status](https://drone.cactifans.org/api/badges/canghai908/zbxtable/status.svg?ref=refs/heads/2.1)](https://drone.cactifans.org/canghai908/zbxtable) 6 | 7 | ZbxTable is a Zabbix report system developed using Go language. 8 | 9 | ## Features 10 | 11 | - Custom drawing topology 12 | - Device classification display and export 13 | - Export Zabbix alert messages to xlsx within a specific time period 14 | - Analyze the alarm messages in a specific time period, alarm Top 10, etc. 15 | 16 | ## Architecture 17 | 18 | ![1](/zbxtable.png) 19 | 20 | ## Component 21 | 22 | ZbxTable: Backend written using [beego framework](https://github.com/astaxie/beego). 23 | 24 | ZbxTable-Web: Front end written using [Vue](https://github.com/vuejs/vue). 25 | 26 | MS-Agent: Installed on Zabbix Server, used to receive alarms generated by Zabbix Server and send to ZbxTable. 27 | 28 | ## Demo 29 | 30 | [https://demo.zbxtable.com](https://demo.zbxtable.com) 31 | 32 | ## Compatibility 33 | 34 | | Zabbix Version | Compatibility | 35 | |:---------------|:-------------:| 36 | | 7.4.x | ✅ | 37 | | 7.2.x | ✅ | 38 | | 7.0.x LTS | ✅ | 39 | | 6.4.x | ✅ | 40 | | 6.2.x | ✅ | 41 | | 6.0.x LTS | ✅ | 42 | | 5.4.x | ✅ | 43 | | 5.2.x | ✅ | 44 | | 5.0.x LTS | ✅ | 45 | | 4.4.x | ✅ | 46 | | 4.2.x | ✅ | 47 | | 4.0.x LTS | ✅ | 48 | | 3.4.x | untested | 49 | | 3.2.x | untested | 50 | | 3.0.x LTS | untested | 51 | 52 | ## Documentation 53 | 54 | [ZbxTable Documentation](https://zbxtable.com) 55 | 56 | ## Code 57 | 58 | **ZbxTable**: [https://github.com/canghai908/zbxtable](https://github.com/canghai908/zbxtable) 59 | 60 | **ZbxTable-Web**: [https://github.com/canghai908/zbxtable-web](https://github.com/canghai908/zbxtable-web) 61 | 62 | **MS-Agent**: [https://github.com/canghai908/ms-agent](https://github.com/canghai908/ms-agent) 63 | 64 | ## Compile 65 | 66 | go >=1.22 67 | 68 | ``` 69 | mkdir -p $GOPATH/src/github.com/canghai908 70 | cd $GOPATH/src/github.com/canghai908 71 | git clone github.com/canghai908/zbxtable.git 72 | cd zbxtable 73 | wget -q -c https://dl.cactifans.com/stable/zbxtable/web-latest.tar.gz && tar xf web-latest.tar.gz 74 | go install github.com/go-bindata/go-bindata/go-bindata@latest 75 | ./control build 76 | ./control pack 77 | ``` 78 | 79 | ## Team 80 | 81 | Back-end development 82 | 83 | [canghai908](https://github.com/canghai908) 84 | 85 | Front-end development 86 | 87 | [ahyiru](https://github.com/ahyiru) 88 | 89 | ## License 90 | 91 | ZbxTable is available under the Apache-2.0 license. See the [LICENSE](LICENSE) file for more info. 92 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | [English](./README.md) | 简体中文 2 | 3 | # ZbxTable 4 | 5 | [![Build Status](https://drone.cactifans.org/api/badges/canghai908/zbxtable/status.svg?ref=refs/heads/2.1)](https://drone.cactifans.org/canghai908/zbxtable) 6 | 7 | ZbxTable 是使用 Go 语言开发的一个 Zabbix 报表系统。 8 | 9 | ## 主要功能: 10 | 11 | - 开箱即用的微信和邮件告警 12 | - 多租户告警消息分发、屏蔽、统计、到处 13 | - 接口流量报表 14 | - 可视化绘制拓扑图 15 | - 设备分类展示及导出 16 | 17 | ## 系统架构 18 | 19 | ![1](/zbxtable.png) 20 | 21 | ## 组件介绍 22 | 23 | ZbxTable: 使用 beego 框架编写的后端程序 24 | 25 | ZbxTable-Web: 使用 Vue 编写的前端 26 | 27 | MS-Agent: 安装在 Zabbix Server 上, 用于接收 Zabbix Server 产生的告警,并发送到 ZbxTable 平台 28 | 29 | ## Demo 30 | 31 | [https://demo.zbxtable.com](https://demo.zbxtable.com) 32 | 33 | ## 兼容性 34 | 35 | | zabbix 版本 | 兼容性 | 36 | |:----------|:-------:| 37 | | 7.4.x | ✅ | 38 | | 7.2.x | ✅ | 39 | | 7.0.x LTS | ✅ | 40 | | 6.4.x | ✅ | 41 | | 6.2.x | ✅ | 42 | | 6.0.x LTS | ✅ | 43 | | 5.4.x | ✅ | 44 | | 5.2.x | ✅ | 45 | | 5.0.x LTS | ✅ | 46 | | 4.4.x | ✅ | 47 | | 4.2.x | ✅ | 48 | | 4.0.x LTS | ✅ | 49 | | 3.4.x | 未测试 | 50 | | 3.2.x | 未测试 | 51 | | 3.0.x LTS | 未测试 | 52 | 53 | ## 文档 54 | 55 | [ZbxTable 文档](https://zbxtable.com) 56 | 57 | ## 源码 58 | 59 | **ZbxTable**: [https://github.com/canghai908/zbxtable](https://github.com/canghai908/zbxtable) 60 | 61 | **ZbxTable-Web**: [https://github.com/canghai908/zbxtable-web](https://github.com/canghai908/zbxtable-web) 62 | 63 | **MS-Agent**: [https://github.com/canghai908/ms-agent](https://github.com/canghai908/ms-agent) 64 | 65 | ## 编译 66 | 67 | 环境:go >=1.22 68 | 69 | ``` 70 | mkdir -p $GOPATH/src/github.com/canghai908 71 | cd $GOPATH/src/github.com/canghai908 72 | git clone github.com/canghai908/zbxtable.git 73 | cd zbxtable 74 | wget -q -c https://dl.cactifans.com/stable/zbxtable/web-latest.tar.gz && tar xf web-latest.tar.gz 75 | go install github.com/go-bindata/go-bindata/go-bindata@latest 76 | ./control build 77 | ./control pack 78 | ``` 79 | 80 | ## Team 81 | 82 | 后端 83 | 84 | [canghai908](https://github.com/canghai908) 85 | 86 | 前端 87 | 88 | [ahyiru](https://github.com/ahyiru) 89 | 90 | ## License 91 | 92 | Nightingale is available under the Apache-2.0 license. See the [LICENSE](LICENSE) file for more info. 93 | -------------------------------------------------------------------------------- /bee.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 0, 3 | "go_install": false, 4 | "watch_ext": [".go"], 5 | "watch_ext_static": [".html", ".tpl", ".js", ".css"], 6 | "dir_structure": { 7 | "watch_all": false, 8 | "controllers": "", 9 | "models": "", 10 | "others": [] 11 | }, 12 | "cmd_args": ["web"], 13 | "envs": [], 14 | "database": { 15 | "driver": "mysql" 16 | }, 17 | "enable_reload": false 18 | } -------------------------------------------------------------------------------- /cmd/uninstallaction.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | "github.com/urfave/cli/v2" 6 | ) 7 | 8 | var ( 9 | // Install cli 10 | Uninstall = &cli.Command{ 11 | Name: "uninstall", 12 | Usage: "Uninstall action", 13 | Action: UninstallAction, 14 | } 15 | ) 16 | 17 | func UninstallAction(*cli.Context) error { 18 | err := CheckZabbix() 19 | if err != nil { 20 | return err 21 | } 22 | //action delete 23 | actionid, err := GetActionID(MSAction) 24 | if err != nil { 25 | logs.Error(err) 26 | return err 27 | } 28 | actionmap := make(map[string]string, 0) 29 | actionmap["params"] = actionid 30 | _, err = API.CallWithError("action.delete", actionmap) 31 | if err != nil { 32 | logs.Error(err) 33 | return err 34 | } 35 | logs.Info("Delete " + MSAction + " action successfully!") 36 | //user delete 37 | userinfo, err := GetUserID(MSUser) 38 | if err != nil { 39 | logs.Error(err) 40 | return err 41 | } 42 | usermap := make(map[string]string, 0) 43 | usermap["params"] = userinfo.Userid 44 | _, err = API.CallWithError("user.delete", usermap) 45 | if err != nil { 46 | logs.Error(err) 47 | return err 48 | } 49 | logs.Info("Delete " + MSUser + " user successfully!") 50 | //usergroup delete 51 | usergroupmap := make(map[string]string, 0) 52 | usergroupmap["params"] = userinfo.Usrgrps[0].Usrgrpid 53 | _, err = API.CallWithError("usergroup.delete", usergroupmap) 54 | if err != nil { 55 | logs.Error(err) 56 | return err 57 | } 58 | logs.Info("Delete " + MSGroup + " group successfully!") 59 | // mediatype delete 60 | mediatypemap := make(map[string]interface{}, 0) 61 | mepar := []string{userinfo.Mediatypes[0].Mediatypeid} 62 | mediatypemap["params"] = mepar 63 | 64 | _, err = API.CallWithError("mediatype.delete", mepar) 65 | if err != nil { 66 | logs.Error(err) 67 | return err 68 | } 69 | logs.Info("Delete " + MSMedia + " mediatype successfully!") 70 | return nil 71 | } 72 | -------------------------------------------------------------------------------- /cmd/update.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "os" 5 | "zbxtable/models" 6 | 7 | "github.com/pterm/pterm" 8 | "github.com/sanbornm/go-selfupdate/selfupdate" 9 | "github.com/urfave/cli/v2" 10 | ) 11 | 12 | const UpdateURL = "http://dl.cactifans.com/stable/" 13 | 14 | var updater = &selfupdate.Updater{ 15 | // Manually update the const, or set it using `go build -ldflags="-X main.VERSION=" -o hello-updater src/hello-updater/main.go` 16 | ApiURL: UpdateURL, // The server hosting `$CmdName/$GOOS-$ARCH.json` which contains the checksum for the binary 17 | BinURL: UpdateURL, // The server hosting the zip file containing the binary application which is a fallback for the patch method 18 | DiffURL: UpdateURL, // The server hosting the binary patch diff for incremental updates 19 | Dir: "update/", // The directory created by the app when run which stores the cktime file 20 | CmdName: "zbxtable", // The app name which is appended to the ApiURL to look for an update 21 | ForceCheck: true, // For this example, always check for an update unless the version is "dev" 22 | } 23 | 24 | func GetVersion(version, gitHash, buildTime string) selfupdate.Updater { 25 | models.Version = version 26 | models.GitHash = gitHash 27 | models.BuildTime = buildTime 28 | updater.CurrentVersion = version 29 | return *updater 30 | } 31 | 32 | var ( 33 | // Install cli 34 | Update = &cli.Command{ 35 | Name: "update", 36 | Usage: "update zbxtable", 37 | Action: update, 38 | } 39 | ) 40 | 41 | // update 更新 42 | func update(*cli.Context) error { 43 | //获取更新信息 44 | UpdateVersion, err := updater.UpdateAvailable() 45 | //更新出错 46 | if err != nil { 47 | pterm.Error.Println("Update failed!", err) 48 | return err 49 | } 50 | //版本需要更新 51 | if UpdateVersion != "" { 52 | pterm.Info.Println("A new version is available!") 53 | //提示用户升级会删除web目录 54 | pterm.Println(pterm.Red("Warning: The upgrade operation will delete the old web directory!!!")) 55 | options := []string{"yes", "no"} 56 | prompt := pterm.DefaultInteractiveContinue.WithDefaultText("Do you want to update now?").WithOptions(options) 57 | result, _ := prompt.Show() 58 | // Print a blank line for better readability 59 | pterm.Println() 60 | // Print the user's input with an info prefix 61 | // As this is a continue prompt, the input should be empty 62 | switch result { 63 | case "yes": 64 | // 删除旧的web备份目录, 65 | // 备份web目录 66 | _ = os.RemoveAll("./.web") 67 | _ = os.Rename("./web", "./.web") 68 | spinnerInfo, _ := pterm.DefaultSpinner.Start("Start updating ...") 69 | err := updater.Update() 70 | if err != nil { 71 | //升级失败 72 | spinnerInfo.Fail("Update failed!", err) 73 | pterm.Println() 74 | return err 75 | } 76 | spinnerInfo.Success("Successfully updated to version ", updater.Info.Version) 77 | spinnerInfo.Success("Next run, I should be ", updater.Info.Version) 78 | pterm.Println() 79 | return nil 80 | default: 81 | return nil 82 | } 83 | 84 | } 85 | pterm.Info.Println("The current version is ", updater.CurrentVersion) 86 | pterm.Info.Println("The latest version is ", updater.Info.Version) 87 | pterm.Info.Println("The current version is the latest version, no need to update!") 88 | return nil 89 | } 90 | -------------------------------------------------------------------------------- /cmd/updateconf.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | "github.com/urfave/cli/v2" 6 | ) 7 | 8 | var ( 9 | //config update 10 | Uc = &cli.Command{ 11 | Name: "uc", 12 | Usage: "Update config file", 13 | Action: updateconfig, 14 | } 15 | ) 16 | 17 | //update config 18 | func updateconfig(*cli.Context) error { 19 | logs.Info("Start upgrading the old configuration file!") 20 | conf := make(map[string]string) 21 | var b = []string{"appname", "httpport", "runmode", "copyrequestbody", "session_timeout", 22 | "dbdriver", "hostname", "username", "dbpsword", "database", "port", 23 | "zabbix_web", "zabbix_user", "zabbix_pass", "token"} 24 | for _, v := range b { 25 | conf[v] = InitConfig(v) 26 | } 27 | err := PreCheckConf(conf["zabbix_web"], conf["zabbix_user"], conf["zabbix_pass"], 28 | conf["dbdriver"], conf["hostname"], conf["username"], conf["dbpsword"], conf["database"], conf["port"]) 29 | if err != nil { 30 | logs.Error(err) 31 | return err 32 | } 33 | err = WriteConf(conf["zabbix_web"], conf["zabbix_user"], conf["zabbix_pass"], 34 | conf["dbdriver"], conf["hostname"], conf["username"], conf["dbpsword"], conf["database"], conf["port"], 35 | conf["httpport"], conf["runmode"], conf["session_timeout"], conf["token"]) 36 | if err != nil { 37 | logs.Error(err) 38 | return err 39 | } 40 | logs.Info("Successfully upgraded the old configuration file!") 41 | return nil 42 | } 43 | 44 | //check conf 45 | func PreCheckConf(zabbix_web, zabbix_user, zabbix_pass, 46 | dbtype, dbhost, dbuser, dbpass, dbname, dbport string) error { 47 | err := CheckDb(dbtype, dbhost, dbuser, dbpass, dbname, dbport) 48 | if err != nil { 49 | logs.Error(err) 50 | return err 51 | } 52 | logs.Info("Connected to database " + dbname + " successfully!") 53 | version, err := CheckZabbixAPI(zabbix_web, zabbix_user, zabbix_pass) 54 | if err != nil { 55 | logs.Error(err) 56 | return err 57 | } 58 | logs.Info("Connected to zabbix web successfully!Zabbix version is :", version) 59 | return nil 60 | } 61 | 62 | // 63 | ////check conf 64 | //func PreCheckConf() error { 65 | // cfg, err := ini.Load("./conf/app.conf") 66 | // if err != nil { 67 | // logs.Error(err) 68 | // return err 69 | // } 70 | // conf := make(map[string]string) 71 | // var b = []string{"dbtype", "dbhost", "dbuser", "dbpass", "dbname", "dbport", 72 | // "zabbix_web", "zabbix_user", "zabbix_pass"} 73 | // for _, v := range b { 74 | // p, err := cfg.Section("").GetKey(v) 75 | // if err != nil { 76 | // logs.Error(err) 77 | // return err 78 | // } 79 | // conf[v] = p.String() 80 | // } 81 | // err = CheckDb(InitConfig("dbtype"), conf["dbhost"], conf["dbuser"], conf["dbpass"], conf["dbname"], conf["dbport"]) 82 | // if err != nil { 83 | // logs.Error(err) 84 | // return err 85 | // } 86 | // logs.Info("Connected to database " + conf["dbname"] + " successfully!") 87 | // version, err := CheckZabbix(conf["zabbix_web"], conf["zabbix_user"], conf["zabbix_pass"]) 88 | // if err != nil { 89 | // logs.Error(err) 90 | // return err 91 | // } 92 | // logs.Info("Connected to zabbix web successfully!Zabbix version is :", version) 93 | // return nil 94 | //} 95 | -------------------------------------------------------------------------------- /conf/app.conf: -------------------------------------------------------------------------------- 1 | ; zbxtable 2 | appname = zbxtable 3 | httpport = 8085 4 | runmode = dev 5 | timeout = 12 6 | token = de0c0d234f054c74b3d87d715f69afb6 7 | copyrequestbody = true 8 | EnableDocs = true 9 | 10 | ; log 11 | log_level = 6 12 | log_path = logs/app.log 13 | maxlines = 1000 14 | maxsize = 0 15 | maxdays = 10 16 | daily = true 17 | 18 | ; database 19 | dbtype = mysql 20 | dbhost = 127.0.0.1 21 | dbuser = zbxtable 22 | dbpass = zbxtablepwd123 23 | dbname = zbxtable 24 | dbport = 3306 25 | 26 | ;redis 27 | redis_host = 127.0.0.1 28 | redis_port = 6379 29 | redis_pass = 30 | redis_db = 8 31 | 32 | ; zabbix 33 | zabbix_web = http://192.168.10.200/zabbix 34 | zabbix_user = Admin 35 | zabbix_pass = xxxxx 36 | zabbix_token = 37 | 38 | ; mail 39 | email_from = xxx@qq.com 40 | email_port = 465 41 | email_host = smtp.qq.com 42 | email_isSSl = true 43 | email_secret = xxxxx 44 | email_nickname = 运维监控 45 | 46 | ; wechat 47 | wechat_agentid = 1 48 | wechat_corpid = wxa7c63522727b7790 49 | wechat_secret = 5HA0o9bkvMMFDp8yFswwZIifoSDtmCJ4k 50 | 51 | # Ollama配置 52 | ollama_host = "http://192.168.6.80:11434" 53 | ollama_model ="deepseek-r1:32b" -------------------------------------------------------------------------------- /control: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # release version 3 | version=2.1.8 4 | 5 | CWD=$(cd $(dirname $0)/; pwd) 6 | cd $CWD 7 | 8 | usage() 9 | { 10 | echo $"Usage: $0 {build|pack}" 11 | exit 0 12 | } 13 | 14 | build() 15 | { 16 | export CGO_ENABLED=0 17 | go generate 18 | go build -v -ldflags "-X main.version=${version} -X main.buildTime=`date -u '+%Y-%m-%d_%I:%M:%S%p'` -X main.gitHash=`git rev-parse HEAD`" -o zbxtable main.go 19 | } 20 | 21 | pack() 22 | { 23 | mkdir -p zbxtable-${version}/conf 24 | cp zbxtable zbxtable-${version}/ 25 | cp zbxtable.service zbxtable-${version}/ 26 | cp nginx.conf zbxtable-${version}/ 27 | cp zbxtable.init zbxtable-${version}/ 28 | cp conf/app.conf zbxtable-${version}/conf 29 | tar zcvf zbxtable-${version}.tar.gz zbxtable-${version}/ 30 | } 31 | 32 | case "$1" in 33 | build) 34 | build $2 35 | ;; 36 | pack) 37 | pack $2 38 | ;; 39 | *) 40 | usage 41 | esac 42 | -------------------------------------------------------------------------------- /controllers/ai.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "io" 8 | "net/http" 9 | 10 | "github.com/astaxie/beego" 11 | ) 12 | 13 | type AIController struct { 14 | BaseController 15 | } 16 | 17 | type ChatRequest struct { 18 | Message string `json:"message"` 19 | } 20 | 21 | type Message struct { 22 | Role string `json:"role"` 23 | Content string `json:"content"` 24 | } 25 | 26 | type ChatResponse struct { 27 | Model string `json:"model"` 28 | CreatedAt string `json:"created_at"` 29 | Message Message `json:"message"` 30 | Done bool `json:"done"` 31 | } 32 | 33 | // AIRes 统一响应格式 34 | var AIRes struct { 35 | Code int `json:"code"` 36 | Message string `json:"message"` 37 | Data string `json:"data"` 38 | } 39 | 40 | // URLMapping ... 41 | func (c *AIController) URLMapping() { 42 | c.Mapping("Chat", c.Chat) 43 | } 44 | 45 | // Chat ... 46 | // @Title 流式聊天接口 47 | // @Description 调用Ollama API进行流式对话 48 | // @Param message body string true "聊天消息内容" 49 | // @Success 200 {object} ChatResponse 50 | // @router /chat [post] 51 | func (c *AIController) Chat() { 52 | // 设置响应头 53 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "text/event-stream") 54 | c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-cache") 55 | c.Ctx.ResponseWriter.Header().Set("Connection", "keep-alive") 56 | 57 | // 解析请求体 58 | var userReq ChatRequest 59 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &userReq); err != nil { 60 | AIRes.Code = 500 61 | AIRes.Message = err.Error() 62 | c.Data["json"] = AIRes 63 | c.ServeJSON() 64 | return 65 | } 66 | 67 | // 构造系统提示词 68 | systemPrompt := Message{ 69 | Role: "system", 70 | Content: "你是一个专业的运维分析师,请分析用户提供的问题并给出专业的建议。", 71 | } 72 | 73 | // 构造Ollama请求 74 | ollamaReq := struct { 75 | Model string `json:"model"` 76 | Messages []Message `json:"messages"` 77 | Stream bool `json:"stream"` 78 | }{ 79 | Model: beego.AppConfig.DefaultString("ollama_model", "deepseek-r1:32b"), 80 | Stream: true, 81 | Messages: []Message{ 82 | systemPrompt, 83 | { 84 | Role: "user", 85 | Content: userReq.Message, 86 | }, 87 | }, 88 | } 89 | 90 | jsonData, err := json.Marshal(ollamaReq) 91 | if err != nil { 92 | AIRes.Code = 500 93 | AIRes.Message = err.Error() 94 | c.Data["json"] = AIRes 95 | c.ServeJSON() 96 | return 97 | } 98 | 99 | // 从配置文件获取Ollama地址 100 | ollamaHost := beego.AppConfig.DefaultString("ollama_host", "http://localhost:11434") 101 | ollamaURL := fmt.Sprintf("%s/api/chat", ollamaHost) 102 | 103 | // 发送请求到Ollama 104 | resp, err := http.Post(ollamaURL, "application/json", bytes.NewBuffer(jsonData)) 105 | if err != nil { 106 | AIRes.Code = 500 107 | AIRes.Message = err.Error() 108 | c.Data["json"] = AIRes 109 | c.ServeJSON() 110 | return 111 | } 112 | defer resp.Body.Close() 113 | 114 | // 创建reader 115 | reader := bufio.NewReader(resp.Body) 116 | 117 | // 流式读取响应 118 | for { 119 | line, err := reader.ReadBytes('\n') 120 | if err != nil { 121 | if err == io.EOF { 122 | break 123 | } 124 | return 125 | } 126 | 127 | // 解析响应 128 | var response ChatResponse 129 | if err := json.Unmarshal(line, &response); err != nil { 130 | continue 131 | } 132 | 133 | // 发送数据 134 | if response.Message.Content != "" { 135 | c.Ctx.WriteString(response.Message.Content) 136 | c.Ctx.ResponseWriter.Flush() 137 | } 138 | 139 | // 如果响应完成,退出循环 140 | if response.Done { 141 | break 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /controllers/base.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | jwtbeego "github.com/canghai908/jwt-beego" 6 | jsoniter "github.com/json-iterator/go" 7 | "net/http" 8 | ) 9 | 10 | var json = jsoniter.Config{ 11 | EscapeHTML: false, 12 | SortMapKeys: true, 13 | ValidateJsonRawMessage: true, 14 | }.Froze() 15 | 16 | // BaseController use 17 | type BaseController struct { 18 | beego.Controller 19 | } 20 | 21 | func (c *BaseController) ServeJSON() { 22 | c.Ctx.Output.Header("Content-Type", "application/json; charset=utf-8") 23 | var err error 24 | data := c.Data["json"] 25 | encoder := json.NewEncoder(c.Ctx.Output.Context.ResponseWriter) 26 | encoder.SetEscapeHTML(false) 27 | encoder.SetIndent("", " ") 28 | err = encoder.Encode(data) 29 | if err != nil { 30 | http.Error(c.Ctx.Output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError) 31 | return 32 | } 33 | } 34 | 35 | // Resp all 36 | type Resp struct { 37 | Code int `json:"code"` 38 | Message string `json:"message"` 39 | Data []struct { 40 | Items string `json:"items"` 41 | Totals int `json:"totals"` 42 | } `json:"data"` 43 | } 44 | 45 | // Res var 46 | var Res = &Resp{} 47 | 48 | // Tuser is userinfo 49 | var Tuser string 50 | 51 | // Prepare login 52 | func (c *BaseController) Prepare() { 53 | tokenString := c.Ctx.Request.Header.Get("X-Token") 54 | et := jwtbeego.EasyToken{} 55 | valid, iss, _ := et.ValidateToken(tokenString) 56 | if !valid { 57 | type resp struct { 58 | Code int `json:"code"` 59 | Message string `json:"message"` 60 | Data struct { 61 | Items string `json:"items"` 62 | Total int `json:"total"` 63 | } `json:"data"` 64 | } 65 | var res resp 66 | res.Code = 50014 67 | res.Message = "token过期或非法的token" 68 | c.Data["json"] = res 69 | c.ServeJSON() 70 | } 71 | Tuser = iss 72 | return 73 | } 74 | -------------------------------------------------------------------------------- /controllers/event_log.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "strconv" 5 | "zbxtable/models" 6 | ) 7 | 8 | type EventLogController struct { 9 | BaseController 10 | } 11 | 12 | var EveLogResp models.EventLogRes 13 | 14 | // URLMapping ... 15 | func (c *EventLogController) URLMapping() { 16 | c.Mapping("GetOne", c.GetOne) 17 | } 18 | 19 | // GetOne ... 20 | // @Title Get One 21 | // @Description get eventlog by id 22 | // @Param X-Token header string true "x-token in header" 23 | // @Param id path string true "The key for staticblock" 24 | // @Success 200 {object} models.Alarm 25 | // @Failure 403 :id is empty 26 | // @router /:id [get] 27 | func (c *EventLogController) GetOne() { 28 | idStr := c.Ctx.Input.Param(":id") 29 | id, _ := strconv.Atoi(idStr) 30 | v, err := models.GetEventLogByAlarmID(id) 31 | if err != nil { 32 | EveLogResp.Code = 500 33 | EveLogResp.Message = "获取失败" 34 | EveLogResp.Data.Items = nil 35 | EveLogResp.Data.Total = 0 36 | } else { 37 | EveLogResp.Code = 200 38 | EveLogResp.Message = "获取成功" 39 | EveLogResp.Data.Items = v 40 | EveLogResp.Data.Total = int64(len(v)) 41 | c.Data["json"] = v 42 | } 43 | c.Data["json"] = EveLogResp 44 | c.ServeJSON() 45 | } 46 | -------------------------------------------------------------------------------- /controllers/graph.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "zbxtable/models" 8 | ) 9 | 10 | // GraphController operations for Host 11 | type GraphController struct { 12 | BaseController 13 | } 14 | 15 | //GraphRes restp 16 | var GraphRes models.GraphList 17 | 18 | // URLMapping ... 19 | func (c *GraphController) URLMapping() { 20 | //c.Mapping("Post", c.Post) 21 | c.Mapping("Post", c.Post) 22 | c.Mapping("Exp", c.Exp) 23 | 24 | } 25 | 26 | // Post t 27 | // @Title 根据Hostid查看主机图形 28 | // @Description get graphs by hostid 29 | // @Param X-Token header string true "x-token in header" 30 | // @Param body body models.GraphListQuery true "body for Host content" 31 | // @Success 200 {object} models.GraphInfo 32 | // @Failure 403 :id is empty 33 | // @router /:hostid [post] 34 | func (c *GraphController) Post() { 35 | var v models.GraphListQuery 36 | err := json.Unmarshal(c.Ctx.Input.RequestBody, &v) 37 | if err != nil { 38 | GraphRes.Code = 200 39 | GraphRes.Message = err.Error() 40 | c.Data["json"] = GraphRes 41 | c.ServeJSON() 42 | return 43 | } 44 | 45 | var Start, End int64 46 | 47 | //如果时间为空,默认为一周 48 | if len(v.Period) == 0 || v.Period[0] == "" || v.Period[1] == "" { 49 | tEnd := time.Now() 50 | End = tEnd.Unix() 51 | Start = tEnd.Add(-168 * time.Hour).Unix() 52 | } 53 | 54 | timeLayout := "2006-01-02 15:04:05" 55 | loc, _ := time.LoadLocation("Local") 56 | st, _ := time.ParseInLocation(timeLayout, v.Period[0], loc) 57 | en, _ := time.ParseInLocation(timeLayout, v.Period[1], loc) 58 | Start = st.Unix() 59 | End = en.Unix() 60 | 61 | id, _ := strconv.Atoi(v.Hostid) 62 | vv, count, err := models.GetGraphByHostID(id, Start, End) 63 | if err != nil { 64 | GraphRes.Code = 500 65 | GraphRes.Message = "获取图形数据错误" 66 | c.Data["json"] = GraphRes 67 | c.ServeJSON() 68 | return 69 | } 70 | GraphRes.Code = 200 71 | GraphRes.Message = "获取数据成功" 72 | GraphRes.Data.Items = vv 73 | GraphRes.Data.Total = count 74 | c.Data["json"] = GraphRes 75 | c.ServeJSON() 76 | } 77 | 78 | // Exp get 79 | // @Title 导主机组或主机图形为PDF 80 | // @Description get graphs by hostid 81 | // @Param X-Token header string true "x-token in header" 82 | // @Param body body models.GraphExpQuery true "body for Host content" 83 | // @Success 200 {object} models.GraphInfo 84 | // @Failure 403 :id is empty 85 | // @router /exp [post] 86 | func (c *GraphController) Exp() { 87 | var v models.GraphExpQuery 88 | err := json.Unmarshal(c.Ctx.Input.RequestBody, &v) 89 | if err != nil { 90 | GraphRes.Code = 200 91 | GraphRes.Message = err.Error() 92 | c.Data["json"] = GraphRes 93 | c.ServeJSON() 94 | return 95 | } 96 | 97 | var Start, End string 98 | 99 | //如果时间为空,默认为一周 100 | if len(v.Period) == 0 || v.Period[0] == "" || v.Period[1] == "" { 101 | tEnd := time.Now() 102 | End = tEnd.Format("2006-01-02 15:04:05") 103 | Start = tEnd.Add(-168 * time.Hour).Format("2006-01-02 15:04:05") 104 | } 105 | 106 | timeLayout := "2006-01-02 15:04:05" 107 | loc, _ := time.LoadLocation("Local") 108 | st, _ := time.ParseInLocation(timeLayout, v.Period[0], loc) 109 | en, _ := time.ParseInLocation(timeLayout, v.Period[1], loc) 110 | Start = st.Format("2006-01-02 15:04:05") 111 | End = en.Format("2006-01-02 15:04:05") 112 | vvv, err := models.SaveImagePDF(v.Hostids, Start, End) 113 | // vv, err := ch 114 | if err != nil { 115 | GraphRes.Code = 500 116 | GraphRes.Message = "获取图形数据错误" 117 | c.Data["json"] = GraphRes 118 | c.ServeJSON() 119 | return 120 | } 121 | c.Ctx.Output.Header("Content-Type", "application/octet-stream") 122 | c.Ctx.Output.Header("Content-Disposition", "attachment; filename=graph_export.pdf") 123 | c.Ctx.Output.Header("Content-Transfer-Encoding", "binary") 124 | c.Ctx.Output.Header("Access-Control-Expose-Headers", "Content-Disposition") 125 | c.Ctx.Output.Status = 200 126 | c.Ctx.Output.EnableGzip = true 127 | c.Ctx.Output.Context.Output.Body(vvv) 128 | return 129 | } 130 | -------------------------------------------------------------------------------- /controllers/group.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/tidwall/gjson" 5 | "strconv" 6 | "zbxtable/models" 7 | ) 8 | 9 | type GroupControllers struct { 10 | BaseController 11 | } 12 | 13 | var GrooupRes models.GroupResp 14 | 15 | func (c *GroupControllers) URLMapping() { 16 | c.Mapping("Get", c.Get) 17 | c.Mapping("Post", c.Post) 18 | c.Mapping("Delete", c.Delete) 19 | c.Mapping("Put", c.Put) 20 | c.Mapping("PutMembers", c.PutMembers) 21 | //c.Mapping("GetReportOne", c.GetReportOne) 22 | //c.Mapping("CreateReport", c.CreateReport) 23 | ////c.Mapping("InitTopology", c.InitTopology) 24 | //c.Mapping("Delete", c.Delete) 25 | //c.Mapping("Put", c.Put) 26 | //c.Mapping("UpdateReportStatus", c.UpdateReportStatus) 27 | } 28 | 29 | // Get ... 30 | // @Title 获取组列表 31 | // @Description 获取组列表 32 | // @Param X-Token header string true "X-Token" 33 | // @Param page query string false "页数" 34 | // @Param limit query string false "每页数" 35 | // @Param name query string false "拓扑名称" 36 | // @Success 200 {object} models.Topology 37 | // @Failure 403 38 | // @router / [get] 39 | func (c *GroupControllers) Get() { 40 | page := c.Ctx.Input.Query("page") 41 | limit := c.Ctx.Input.Query("limit") 42 | name := c.Ctx.Input.Query("name") 43 | count, hs, err := models.GetGroup(page, limit, Tuser, name) 44 | if err != nil { 45 | GrooupRes.Code = 500 46 | GrooupRes.Message = err.Error() 47 | GrooupRes.Data.Items = nil 48 | GrooupRes.Data.Total = 0 49 | } else { 50 | GrooupRes.Code = 200 51 | GrooupRes.Message = "获取数据成功" 52 | GrooupRes.Data.Items = hs 53 | GrooupRes.Data.Total = count 54 | } 55 | c.Data["json"] = GrooupRes 56 | c.ServeJSON() 57 | } 58 | 59 | // Post ... 60 | // @Title 新建用户组 61 | // @Description 新建用户 62 | // @Param X-Token header string true "X-Token" 63 | // @Param body body models.Manager true "manager" 64 | // @Success 200 {object} models.Topology 65 | // @Failure 403 66 | // @router / [post] 67 | func (c *GroupControllers) Post() { 68 | name := gjson.Get(string(c.Ctx.Input.RequestBody), "name").String() 69 | note := gjson.Get(string(c.Ctx.Input.RequestBody), "note").String() 70 | v := models.UserGroup{Name: name, Note: note} 71 | _, err := models.AddUserGroup(&v) 72 | if err != nil { 73 | GrooupRes.Code = 500 74 | GrooupRes.Message = err.Error() 75 | } else { 76 | GrooupRes.Code = 200 77 | GrooupRes.Message = "创建用户组成功" 78 | } 79 | GrooupRes.Data.Items = nil 80 | GrooupRes.Data.Total = 1 81 | c.Data["json"] = GrooupRes 82 | c.ServeJSON() 83 | } 84 | 85 | // Put ... 86 | // @Title 更新用户组信息 87 | // @Description 更新用户组信息 88 | // @Param X-Token header string true "X-Token" 89 | // @Param body body models.UserGroup true "UserGroup" 90 | // @Success 200 {object} models.UserResp 91 | // @Failure 403 92 | // @router /:id [put] 93 | func (c *GroupControllers) Put() { 94 | idStr := c.Ctx.Input.Param(":id") 95 | id, err := strconv.Atoi(idStr) 96 | if err != nil { 97 | GrooupRes.Code = 500 98 | GrooupRes.Message = err.Error() 99 | GrooupRes.Data.Items = nil 100 | GrooupRes.Data.Total = 0 101 | c.Data["json"] = GrooupRes 102 | c.ServeJSON() 103 | } 104 | name := gjson.Get(string(c.Ctx.Input.RequestBody), "name").String() 105 | note := gjson.Get(string(c.Ctx.Input.RequestBody), "note").String() 106 | v := models.UserGroup{ID: id, Name: name, Note: note} 107 | err = models.UpdateUserGroup(&v, Tuser) 108 | if err != nil { 109 | GrooupRes.Code = 500 110 | GrooupRes.Message = err.Error() 111 | } else { 112 | GrooupRes.Code = 200 113 | GrooupRes.Message = "修改成功" 114 | } 115 | GrooupRes.Data.Items = nil 116 | GrooupRes.Data.Total = 0 117 | c.Data["json"] = GrooupRes 118 | c.ServeJSON() 119 | } 120 | 121 | // PutMembers ... 122 | // @Title 更新组成员 123 | // @Description 更新组成员 124 | // @Param X-Token header string true "X-Token" 125 | // @Param body body models.UserGroup true "UserGroup" 126 | // @Success 200 {object} models.UserResp 127 | // @Failure 403 128 | // @router /member/:id [put] 129 | func (c *GroupControllers) PutMembers() { 130 | idStr := c.Ctx.Input.Param(":id") 131 | id, err := strconv.Atoi(idStr) 132 | if err != nil { 133 | GrooupRes.Code = 500 134 | GrooupRes.Message = err.Error() 135 | GrooupRes.Data.Items = nil 136 | GrooupRes.Data.Total = 0 137 | c.Data["json"] = GrooupRes 138 | c.ServeJSON() 139 | } 140 | member := gjson.Get(string(c.Ctx.Input.RequestBody), "member").String() 141 | //member := c.GetString("jsoninfo") 142 | v := models.UserGroup{ID: id, Member: member} 143 | err = models.UpdateGroupMember(&v, Tuser) 144 | if err != nil { 145 | GrooupRes.Code = 500 146 | GrooupRes.Message = err.Error() 147 | } else { 148 | GrooupRes.Code = 200 149 | GrooupRes.Message = "修改成功" 150 | } 151 | GrooupRes.Data.Items = nil 152 | GrooupRes.Data.Total = 0 153 | c.Data["json"] = GrooupRes 154 | c.ServeJSON() 155 | } 156 | 157 | // Delete ... 158 | // @Title 删除群组 159 | // @Description 删除群组 160 | // @Param X-Token header string true "X-Token" 161 | // @Param id path string true "The id you want to delete" 162 | // @Success 200 {object} models.UserResp 163 | // @Failure 403 164 | // @router /:id [delete] 165 | func (c *GroupControllers) Delete() { 166 | idStr := c.Ctx.Input.Param(":id") 167 | id, err := strconv.Atoi(idStr) 168 | if err != nil { 169 | GrooupRes.Code = 500 170 | GrooupRes.Message = err.Error() 171 | GrooupRes.Data.Items = nil 172 | GrooupRes.Data.Total = 0 173 | c.Data["json"] = GrooupRes 174 | c.ServeJSON() 175 | } 176 | if err := models.DeleteGroup(id, Tuser); err == nil { 177 | GrooupRes.Code = 200 178 | GrooupRes.Message = "删除成功" 179 | } else { 180 | GrooupRes.Code = 500 181 | GrooupRes.Message = err.Error() 182 | GrooupRes.Message = "修改成功" 183 | } 184 | GrooupRes.Data.Items = nil 185 | GrooupRes.Data.Total = 0 186 | c.Data["json"] = GrooupRes 187 | c.ServeJSON() 188 | } 189 | -------------------------------------------------------------------------------- /controllers/history.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "time" 5 | "zbxtable/models" 6 | ) 7 | 8 | // HistoryController 监控详情数据获取 9 | type HistoryController struct { 10 | BaseController 11 | } 12 | 13 | //HistoryRes is used 14 | var HistoryRes models.HistoryList 15 | 16 | // URLMapping ... 17 | func (c *HistoryController) URLMapping() { 18 | c.Mapping("GetHistoryByItemID", c.GetHistoryByItemID) 19 | } 20 | 21 | // GetHistoryByItemID controller 22 | // @Title 监控详情数据获取 23 | // @Description 根据ItemID、item类型、开始、结束时间获取监控数据 24 | // @Param X-Token header string true "x-token in header" 25 | // @Param body body models.HistoryQuery true "查询" 26 | // @Success 200 {object} models.History 27 | // @Failure 403 :id is empty 28 | // @router / [post] 29 | func (c *HistoryController) GetHistoryByItemID() { 30 | var v models.HistoryQuery 31 | err := json.Unmarshal(c.Ctx.Input.RequestBody, &v) 32 | if err != nil { 33 | HistoryRes.Code = 500 34 | HistoryRes.Message = err.Error() 35 | c.Data["json"] = HistoryRes 36 | c.ServeJSON() 37 | return 38 | } 39 | var Start, End int64 40 | //如果时间为空,默认为10分钟 41 | if len(v.Period) == 0 || v.Period[0] == "" || v.Period[1] == "" { 42 | tEnd := time.Now() 43 | End = tEnd.Unix() 44 | Start = tEnd.Add(-10 * time.Minute).Unix() 45 | } 46 | timeLayout := "2006-01-02 15:04:05" 47 | loc, _ := time.LoadLocation("Local") 48 | st, _ := time.ParseInLocation(timeLayout, v.Period[0], loc) 49 | en, _ := time.ParseInLocation(timeLayout, v.Period[1], loc) 50 | Start = st.Unix() 51 | End = en.Unix() 52 | his, err := models.GetHistoryByItemID(v.Itemids, v.History, Start, End) 53 | if err != nil { 54 | HistoryRes.Code = 500 55 | HistoryRes.Message = err.Error() 56 | c.Data["json"] = HistoryRes 57 | c.ServeJSON() 58 | return 59 | } 60 | HistoryRes.Code = 200 61 | HistoryRes.Message = "获取成功" 62 | HistoryRes.Data.Items = his 63 | c.Data["json"] = HistoryRes 64 | c.ServeJSON() 65 | return 66 | } 67 | -------------------------------------------------------------------------------- /controllers/histotry_graph.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | type EchartController struct { 4 | BaseController 5 | } 6 | 7 | //URLMapping st 8 | func (c *EchartController) URLMapping() { 9 | c.Mapping("GetHistory", c.GetHistory) 10 | } 11 | 12 | // GetHistory controller 13 | // @Title Get One 14 | // @Description get item by key 15 | // @Param X-Token header string true "x-token in header" 16 | // @Param item_id query string false "The key for item" 17 | // @Param begin query string false "history type" 18 | // @Param end query int false "The key for limit" 19 | // @Success 200 {object} models.Item 20 | // @Failure 403 :id is empty 21 | // @router /history [get] 22 | func (*EchartController) GetHistory() { 23 | // var p models.Item 24 | // p.Itemid 25 | // p, err := models.GetApplicationByHostid(10084) 26 | // if err != nil { 27 | // log.Println(err) 28 | // } 29 | // fmt.Println(p) 30 | // data, err := models.GetHistoryByItemIDNewP(23296, 1590390322, 1590476723) 31 | // if err != nil { 32 | // log.Println(err) 33 | // } 34 | // fmt.Println(data) 35 | } 36 | -------------------------------------------------------------------------------- /controllers/host_groups.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | // HostGroupsController operations for History 8 | type HostGroupsController struct { 9 | BaseController 10 | } 11 | 12 | //HostGroupsRes is used 13 | var HostGroupsRes models.HostGroupsList 14 | 15 | // URLMapping ... 16 | func (c *HostGroupsController) URLMapping() { 17 | c.Mapping("GetList", c.GetList) 18 | c.Mapping("GetAll", c.GetAll) 19 | c.Mapping("GetHostByGroupID", c.GetHostByGroupID) 20 | c.Mapping("GetGroup", c.GetGroup) 21 | } 22 | 23 | // GetList Gaa 24 | // @Title Get All groups 25 | // @Description get groups 26 | // @Param X-Token header string true "x-token in header" 27 | // @Success 200 {object} models.Alarm 28 | // @Failure 403 29 | // @router /list [get] 30 | func (c *HostGroupsController) GetList() { 31 | var HostGroupsRes models.HostTreeList 32 | hs, cnt, err := models.GetAllHostGroupsList() 33 | 34 | if err != nil { 35 | HostGroupsRes.Code = 401 36 | HostGroupsRes.Message = err.Error() 37 | c.Data["json"] = HostGroupsRes 38 | } else { 39 | HostGroupsRes.Code = 200 40 | HostGroupsRes.Message = "获取数据成功" 41 | HostGroupsRes.Data.Items = hs 42 | HostGroupsRes.Data.Total = cnt 43 | c.Data["json"] = HostGroupsRes 44 | } 45 | c.ServeJSON() 46 | } 47 | 48 | // GetList Gaa 49 | // @Title Get All groups 50 | // @Description get groups 51 | // @Param X-Token header string true "x-token in header" 52 | // @Success 200 {object} models.Alarm 53 | // @Failure 403 54 | // @router /all [get] 55 | func (c *HostGroupsController) GetGroup() { 56 | var HostGroupsRes models.HostTreeList 57 | hs, cnt, err := models.GetAllGroupsList() 58 | 59 | if err != nil { 60 | HostGroupsRes.Code = 401 61 | HostGroupsRes.Message = err.Error() 62 | c.Data["json"] = HostGroupsRes 63 | } else { 64 | HostGroupsRes.Code = 200 65 | HostGroupsRes.Message = "获取数据成功" 66 | HostGroupsRes.Data.Items = hs 67 | HostGroupsRes.Data.Total = cnt 68 | c.Data["json"] = HostGroupsRes 69 | } 70 | c.ServeJSON() 71 | } 72 | 73 | // GetAll 获取主机组分页显示 74 | // @Title Get All groups 75 | // @Description 获获取主机组分页显示 76 | // @Param X-Token header string true "x-token in header" 77 | // @Param page query string false "Sorted-by fields. e.g. col1,col2 ..." 78 | // @Param limit query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 79 | // @Param groups query string false "Limit the size of result set. Must be an integer" 80 | // @Success 200 {object} models.Alarm 81 | // @Failure 403 82 | // @router / [get] 83 | func (c *HostGroupsController) GetAll() { 84 | page := c.Ctx.Input.Query("page") 85 | limit := c.Ctx.Input.Query("limit") 86 | groups := c.Ctx.Input.Query("groups") 87 | hs, cnt, err := models.GetAllHostGroups(page, limit, groups) 88 | if err != nil { 89 | HostGroupsRes.Code = 401 90 | HostGroupsRes.Message = err.Error() 91 | c.Data["json"] = HostGroupsRes 92 | c.ServeJSON() 93 | } else { 94 | HostGroupsRes.Code = 200 95 | HostGroupsRes.Message = "获取数据成功" 96 | HostGroupsRes.Data.Items = hs 97 | HostGroupsRes.Data.Total = cnt 98 | c.Data["json"] = HostGroupsRes 99 | } 100 | c.ServeJSON() 101 | } 102 | 103 | // GetHostByGroupID func 104 | // @Title Get All Hosts 105 | // @Description get hosts 106 | // @Param X-Token header string true "x-token in header" 107 | // @Param id path string true "The key for staticblock" 108 | // @Success 200 {object} models.Alarm 109 | // @Failure 403 110 | // @router /list/:id [get] 111 | func (c *HostGroupsController) GetHostByGroupID() { 112 | GroupID := c.Ctx.Input.Param(":id") 113 | hs, err := models.GetHostsByGroupID(GroupID) 114 | var HostsByGroupIDRes models.HostGroupBYGroupIDList 115 | if err != nil { 116 | HostsByGroupIDRes.Code = 401 117 | HostsByGroupIDRes.Message = err.Error() 118 | } else { 119 | HostsByGroupIDRes.Code = 200 120 | HostsByGroupIDRes.Message = "获取数据成功" 121 | } 122 | HostsByGroupIDRes.Data.Items = hs 123 | c.Data["json"] = HostsByGroupIDRes 124 | c.ServeJSON() 125 | } 126 | -------------------------------------------------------------------------------- /controllers/images.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "compress/gzip" 5 | "crypto/tls" 6 | "github.com/astaxie/beego/logs" 7 | "io" 8 | "io/ioutil" 9 | "net/http" 10 | "net/url" 11 | "strings" 12 | 13 | "github.com/astaxie/beego" 14 | "zbxtable/models" 15 | ) 16 | 17 | // ImagesController operations for Host 18 | type ImagesController struct { 19 | // BaseController 20 | beego.Controller 21 | } 22 | 23 | // URLMapping ... 24 | func (c *ImagesController) URLMapping() { 25 | //c.Mapping("Post", c.Post) 26 | c.Mapping("GetOne", c.GetOne) 27 | } 28 | 29 | // GetOne ... 30 | // @Title Get One 31 | // @Description get Alarm by id 32 | // @Param X-Token header string true "x-token in header" 33 | // @Param id path string true "The key for staticblock" 34 | // @Success 200 {object} models.Alarm 35 | // @Failure 403 :id is empty 36 | // @router /:id [get] 37 | func (c *ImagesController) GetOne() { 38 | idStr := c.Ctx.Input.Param(":id") 39 | var StartTime, EndTime string 40 | all := c.Ctx.Input.Query("from") 41 | b := strings.Split(all, "?") 42 | StartTime = b[0] 43 | EndTime = strings.Split(b[1], "=")[1] 44 | GraphID := idStr 45 | c.Ctx.ResponseWriter.Header().Set("Content-Type", "image/png") 46 | c.Ctx.ResponseWriter.Header().Set("Cache-Control", "no-store, no-cache, must-revalidate, post-check=0, pre-check=0") 47 | c.Ctx.ResponseWriter.Header().Set("Pragma", "no-cache, value") 48 | tr := &http.Transport{ 49 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 50 | } 51 | client1 := &http.Client{tr, nil, 52 | models.JAR, 99999999999999} 53 | ZabbixWeb := models.GetConfKey("zabbix_web") 54 | //imgurl 55 | imgurl := ZabbixWeb + "/chart2.php?" 56 | data := url.Values{} 57 | URL, err := url.Parse(imgurl) 58 | if err != nil { 59 | logs.Error(err) 60 | } 61 | data.Set("graphid", GraphID) 62 | data.Set("from", StartTime) 63 | data.Set("to", EndTime) 64 | data.Set("profileIdx", "web.graphs.filter") 65 | data.Set("height", "200") 66 | data.Set("width", "400") 67 | //Encode rul 68 | URL.RawQuery = data.Encode() 69 | urlPath := URL.String() 70 | reqest1, err := http.NewRequest("GET", urlPath, nil) 71 | if err != nil { 72 | logs.Error(err) 73 | } 74 | reqest1.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") 75 | reqest1.Header.Add("Accept-Encoding", "gzip, deflate") 76 | reqest1.Header.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3") 77 | reqest1.Header.Add("Connection", "keep-alive") 78 | reqest1.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0") 79 | response1, err := client1.Do(reqest1) 80 | if err != nil { 81 | logs.Error(err) 82 | } 83 | defer response1.Body.Close() 84 | if response1.StatusCode == 200 { 85 | var reader io.Reader 86 | switch response1.Header.Get("Content-Encoding") { 87 | case "gzip": 88 | reader, _ = gzip.NewReader(response1.Body) 89 | default: 90 | reader = response1.Body 91 | } 92 | data, err := ioutil.ReadAll(reader) 93 | if err != nil { 94 | logs.Error(err) 95 | } 96 | c.Ctx.ResponseWriter.Write(data) 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /controllers/index.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | // IndexController 首页数据获取 8 | type IndexController struct { 9 | BaseController 10 | } 11 | 12 | // InfoRes resp 13 | var ( 14 | InfoRes models.InfoRes 15 | TopRes models.TopRes 16 | TreeRes models.TreeRes 17 | OverRes models.OverviewRes 18 | VerRes models.VerRes 19 | EgrRes models.EgressRes 20 | SesRes models.SessionRes 21 | ) 22 | 23 | // URLMapping beego 24 | func (c *IndexController) URLMapping() { 25 | c.Mapping("Get", c.GetInfo) 26 | c.Mapping("Router", c.Router) 27 | c.Mapping("GetResrouceTop", c.GetResrouceTop) 28 | c.Mapping("Inventory", c.GetInventory) 29 | c.Mapping("GetOverview", c.GetOverview) 30 | c.Mapping("GetVersion", c.GetVersion) 31 | c.Mapping("GetEgress", c.GetEgress) 32 | c.Mapping("GetZbxSession", c.GetZbxSession) 33 | } 34 | 35 | // routers ... 36 | // @Title 获取异步路由 37 | // @Description 获取异步路由 38 | // @Param X-Token header string true "x-token in header" 39 | // @Success 200 {object} models.Manager 40 | // @Failure 403 :id is empty 41 | // @router /routers [get] 42 | func (c *IndexController) Router() { 43 | var routeRes models.RouRes 44 | info, err := models.GetRouter(Tuser) 45 | if err != nil { 46 | routeRes.Code = 500 47 | routeRes.Message = "获取失败" 48 | routeRes.Data.Items = info 49 | } else { 50 | routeRes.Code = 200 51 | routeRes.Message = "获取成功" 52 | routeRes.Data.Items = info 53 | } 54 | c.Data["json"] = routeRes 55 | c.ServeJSON() 56 | } 57 | 58 | // GetInfo ... 59 | // @Title 首页数据 60 | // @Description 基本信息获取 61 | // @Param X-Token header string true "x-token in header" 62 | // @Success 200 {object} models.Manager 63 | // @Failure 403 :id is empty 64 | // @router /baseinfo/ [get] 65 | func (c *IndexController) GetInfo() { 66 | info, err := models.GetCountHost() 67 | if err != nil { 68 | InfoRes.Code = 500 69 | InfoRes.Message = err.Error() 70 | } else { 71 | InfoRes.Code = 200 72 | InfoRes.Message = "获取成功" 73 | InfoRes.Data.Items = info 74 | } 75 | c.Data["json"] = InfoRes 76 | c.ServeJSON() 77 | } 78 | 79 | // GetLinuxCPUTop ... 80 | // @Title Linux CPU使用率top5 81 | // @Description Linux CPU使用率top5数据 82 | // @Param X-Token header string true "x-token in header" 83 | // @Success 200 {object} models.Manager 84 | // @Failure 403 :id is empty 85 | // @router /lincputop [get] 86 | func (c *IndexController) GetLinuxCPUTop() { 87 | info, err := models.GetCountHost() 88 | if err != nil { 89 | InfoRes.Code = 500 90 | InfoRes.Message = err.Error() 91 | } else { 92 | InfoRes.Code = 200 93 | InfoRes.Message = "获取成功" 94 | InfoRes.Data.Items = info 95 | } 96 | c.Data["json"] = InfoRes 97 | c.ServeJSON() 98 | } 99 | 100 | // GetResrouceTop ... 101 | // @Title 资源使用TopN接口 102 | // @Description 主机资源使用TopN接口 103 | // @Param X-Token header string true "x-token in header" 104 | // @Param host_type query string true "主机类型 VM_WIN VM_LIN" 105 | // @Param metrics_type query string true "指标类型 CPU MEM" 106 | // @Param top_num query string false "TOPN" 107 | // @Success 200 {object} models.TopRes 108 | // @Failure 403 :id is empty 109 | // @router /restop [get] 110 | func (c *IndexController) GetResrouceTop() { 111 | host_type := c.Ctx.Input.Query("host_type") 112 | metrics_type := c.Ctx.Input.Query("metrics_type") 113 | top_num := c.Ctx.Input.Query("top_num") 114 | info, err := models.GetTopList(host_type, metrics_type, top_num) 115 | if err != nil { 116 | TopRes.Code = 500 117 | TopRes.Message = err.Error() 118 | } else { 119 | TopRes.Code = 200 120 | TopRes.Message = "获取成功" 121 | TopRes.Data.Items = info 122 | } 123 | c.Data["json"] = TopRes 124 | c.ServeJSON() 125 | } 126 | 127 | // GetResrouceTop ... 128 | // @Title 获取图谱资源 129 | // @Description 主机资源使用TopN接口 130 | // @Param X-Token header string true "x-token in header" 131 | // @Success 200 {object} models.TopRes 132 | // @Failure 403 :id is empty 133 | // @router /inventory [get] 134 | func (c *IndexController) GetInventory() { 135 | info, err := models.GetInventory() 136 | if err != nil { 137 | TreeRes.Code = 500 138 | TreeRes.Message = err.Error() 139 | } else { 140 | TreeRes.Code = 200 141 | TreeRes.Message = "获取成功" 142 | TreeRes.Data.Items = info 143 | } 144 | c.Data["json"] = TreeRes 145 | c.ServeJSON() 146 | } 147 | 148 | // GetResrouceTop ... 149 | // @Title 获取汇总状态 150 | // @Description 获取汇总状态数据 151 | // @Param X-Token header string true "x-token in header" 152 | // @Success 200 {object} models.TopRes 153 | // @Failure 403 :id is empty 154 | // @router /overview [get] 155 | func (c *IndexController) GetOverview() { 156 | info, err := models.GetOverviewData() 157 | if err != nil { 158 | OverRes.Code = 500 159 | OverRes.Message = err.Error() 160 | } else { 161 | OverRes.Code = 200 162 | OverRes.Message = "获取成功" 163 | OverRes.Data.Items = info 164 | } 165 | c.Data["json"] = OverRes 166 | c.ServeJSON() 167 | } 168 | 169 | // GetResrouceTop ... 170 | // @Title 获取汇总状态 171 | // @Description 获取汇总状态数据 172 | // @Param X-Token header string true "x-token in header" 173 | // @Success 200 {object} models.TopRes 174 | // @Failure 403 :id is empty 175 | // @router /egress [get] 176 | func (c *IndexController) GetEgress() { 177 | info, err := models.GetEgressData() 178 | if err != nil { 179 | EgrRes.Code = 500 180 | EgrRes.Message = err.Error() 181 | EgrRes.Data.Items = info 182 | } else { 183 | EgrRes.Code = 200 184 | EgrRes.Message = "获取成功" 185 | EgrRes.Data.Items = info 186 | } 187 | c.Data["json"] = EgrRes 188 | c.ServeJSON() 189 | } 190 | 191 | // GetVersion 获取版本 192 | // @Title 获取版本 193 | // @Description 获取版本 194 | // @Param X-Token header string true "x-token in header" 195 | // @Success 200 {object} models.TopRes 196 | // @Failure 403 :id is empty 197 | // @router /version [get] 198 | func (c *IndexController) GetVersion() { 199 | VerRes.Code = 200 200 | VerRes.Message = "获取成功" 201 | VerRes.Data.Items.ZabbixVersion = models.ZBX_VER 202 | VerRes.Data.Items.Version = models.Version 203 | VerRes.Data.Items.GitHash = models.GitHash 204 | VerRes.Data.Items.BuildTime = models.BuildTime 205 | c.Data["json"] = VerRes 206 | c.ServeJSON() 207 | } 208 | 209 | // GetZbxSession 获取缓存中的zbx session 210 | // @Title 获取缓存中的zbx session 211 | // @Description 获取缓存中的zbx session 212 | // @Param X-Token header string true "x-token in header" 213 | // @Success 200 {object} models.TopRes 214 | // @Failure 403 :id is empty 215 | // @router /session [get] 216 | func (c *IndexController) GetZbxSession() { 217 | session, err := models.GetZbxSession() 218 | //session, err := models.GetDash("1") 219 | if err != nil { 220 | SesRes.Code = 500 221 | SesRes.Message = err.Error() 222 | } else { 223 | SesRes.Code = 200 224 | SesRes.Message = "获取成功" 225 | SesRes.Data.Items = session 226 | } 227 | c.Data["json"] = SesRes 228 | c.ServeJSON() 229 | } 230 | -------------------------------------------------------------------------------- /controllers/item.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | // 主机监控指标获取 8 | type ItemController struct { 9 | BaseController 10 | } 11 | 12 | // ItemRes rep 13 | var ItemRes models.ItemList 14 | var ItemR models.ItemRes 15 | 16 | // URLMapping ... 17 | func (c *ItemController) URLMapping() { 18 | c.Mapping("GetItemByKey", c.GetItemByKey) 19 | //c.Mapping("GetFlowItem", c.GetFlowItem) 20 | c.Mapping("GetAllItemByKey", c.GetAllItemByKey) 21 | c.Mapping("GetAllTraffficByKey", c.GetAllTrafficByKey) 22 | c.Mapping("GetAllTraffficReceive", c.GetAllTraffficReceive) 23 | } 24 | 25 | // GetItemByKey controller 26 | // @Title 根据hostid及key查找item 27 | // @Description 根据hostid及key查找item 28 | // @Param X-Token header string true "x-token in header" 29 | // @Param hostid query string true "The key for item" 30 | // @Param ItemKey query string true "The key for item" 31 | // @Success 200 {object} models.Item 32 | // @Failure 403 :id is empty 33 | // @router / [get] 34 | func (c *ItemController) GetItemByKey() { 35 | HostID := c.Ctx.Input.Query("host_id") 36 | ItemKey := c.Ctx.Input.Query("item_key") 37 | // id, _ := strconv.Atoi(idStr) 38 | v, err := models.GetItemByKey(HostID, ItemKey) 39 | if err != nil { 40 | c.Data["json"] = err.Error() 41 | } else { 42 | c.Data["json"] = v 43 | } 44 | c.ServeJSON() 45 | } 46 | 47 | // 根据hostid获取主机所有item 48 | // @Title 获取主机所有item 49 | // @Description 根据hostid获取item列表 50 | // @Param X-Token header string true "x-token in header" 51 | // @Param hostid query string true "hostid" 52 | // @Success 200 {object} models.Item 53 | // @Failure 403 54 | // @router /list [get] 55 | func (c *ItemController) GetAllItemByKey() { 56 | HostID := c.Ctx.Input.Query("hostid") 57 | v, count, err := models.GetAllItemByHostID(HostID) 58 | if err != nil { 59 | ItemRes.Code = 500 60 | ItemRes.Message = "获取错误" 61 | } else { 62 | ItemRes.Code = 200 63 | ItemRes.Message = "获取数据成功" 64 | ItemRes.Data.Items = v 65 | ItemRes.Data.Total = count 66 | } 67 | c.Data["json"] = ItemRes 68 | c.ServeJSON() 69 | } 70 | 71 | // 根据hostid获取设备所有流量指标 72 | // @Title 获取设备流量指标Item 73 | // @Description 获取设备流量指标Item 74 | // @Param X-Token header string true "x-token in header" 75 | // @Param hostid query string true "hostid" 76 | // @Success 200 {object} models.Item 77 | // @Failure 403 78 | // @router /traffic [get] 79 | func (c *ItemController) GetAllTrafficByKey() { 80 | HostID := c.Ctx.Input.Query("hostid") 81 | v, count, err := models.GetAllTrafficItemByHostID(HostID) 82 | if err != nil { 83 | ItemR.Code = 500 84 | ItemR.Message = "获取错误" 85 | } else { 86 | ItemR.Code = 200 87 | ItemR.Message = "获取数据成功" 88 | ItemR.Data.Items = v 89 | ItemR.Data.Total = count 90 | } 91 | c.Data["json"] = ItemR 92 | c.ServeJSON() 93 | } 94 | 95 | // 根据hostid获取设备所有出流量 96 | // @Title 获取设备流量指标Item 97 | // @Description 获取设备流量指标Item 98 | // @Param X-Token header string true "x-token in header" 99 | // @Param hostid query string true "hostid" 100 | // @Success 200 {object} models.Item 101 | // @Failure 403 102 | // @router /topotraffic [get] 103 | func (c *ItemController) GetAllTraffficReceive() { 104 | HostID := c.Ctx.Input.Query("hostid") 105 | v, count, err := models.GetReceiveTrafficeItemByHostID(HostID) 106 | if err != nil { 107 | ItemR.Code = 500 108 | ItemR.Message = "获取错误" 109 | } else { 110 | ItemR.Code = 200 111 | ItemR.Message = "获取数据成功" 112 | ItemR.Data.Items = v 113 | ItemR.Data.Total = count 114 | } 115 | c.Data["json"] = ItemR 116 | c.ServeJSON() 117 | } 118 | 119 | //// 根据hostid获取主机所有item 120 | //// @Title 获取主机所有item 121 | //// @Description 根据hostid获取item列表 122 | //// @Param X-Token header string true "x-token in header" 123 | //// @Param hostid query string true "hostid" 124 | //// @Success 200 {object} models.Item 125 | //// @Failure 403 126 | //// @router /list [get] 127 | //func (c *ItemController) GetFlowItem() { 128 | // HostID := c.Ctx.Input.Query("hostid") 129 | // v, count, err := models.GetFlowItemByHostID(HostID) 130 | // if err != nil { 131 | // ItemRes.Code = 500 132 | // ItemRes.Message = "获取错误" 133 | // } else { 134 | // ItemRes.Code = 200 135 | // ItemRes.Message = "获取数据成功" 136 | // ItemRes.Data.Items = v 137 | // ItemRes.Data.Total = count 138 | // } 139 | // c.Data["json"] = ItemRes 140 | // c.ServeJSON() 141 | //} 142 | -------------------------------------------------------------------------------- /controllers/problem.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | //ProblemsController funct 8 | type ProblemsController struct { 9 | BaseController 10 | } 11 | 12 | //ProblemsRes resp 13 | var ProblemsRes models.ProblemsRes 14 | 15 | //URLMapping beego 16 | func (c *ProblemsController) URLMapping() { 17 | c.Mapping("Get", c.GetInfo) 18 | } 19 | 20 | // GetInfo 获取未恢复告警 21 | // @Title 获取未恢复告警据 22 | // @Description 获取未恢复告警 23 | // @Param X-Token header string true "x-token in header" 24 | // @Success 200 {object} models.Manager 25 | // @Failure 403 :id is empty 26 | // @router / [get] 27 | func (c *ProblemsController) GetInfo() { 28 | b, cnt, err := models.GetProblems() 29 | if err != nil { 30 | ProblemsRes.Code = 500 31 | ProblemsRes.Message = err.Error() 32 | } else { 33 | ProblemsRes.Code = 200 34 | ProblemsRes.Message = "获取成功" 35 | ProblemsRes.Data.Items = b 36 | ProblemsRes.Data.Total = cnt 37 | } 38 | c.Data["json"] = ProblemsRes 39 | c.ServeJSON() 40 | } 41 | -------------------------------------------------------------------------------- /controllers/task_log.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "strconv" 5 | "zbxtable/models" 6 | ) 7 | 8 | type TaskLogController struct { 9 | BaseController 10 | } 11 | 12 | var TaskLogRes models.TaskRes 13 | 14 | func (c *TaskLogController) URLMapping() { 15 | c.Mapping("GetTaskByReportID", c.GetTaskByReportID) 16 | c.Mapping("Delete", c.Delete) 17 | //c.Mapping("GetReportOne", c.GetReportOne) 18 | //c.Mapping("CreateReport", c.CreateReport) 19 | ////c.Mapping("InitTopology", c.InitTopology) 20 | //c.Mapping("Delete", c.Delete) 21 | //c.Mapping("Put", c.Put) 22 | //c.Mapping("UpdateReportStatus", c.UpdateReportStatus) 23 | } 24 | 25 | // GetTopologyAll ... 26 | // @Title 获取任务日志 27 | // @Description 获取任务日志 28 | // @Param X-Token header string true "X-Token" 29 | // @Param page query string false "页数" 30 | // @Param limit query string false "每页数" 31 | // @Param name query string false "拓扑名称" 32 | // @Success 200 {object} models.Topology 33 | // @Failure 403 34 | // @router / [get] 35 | func (c *TaskLogController) GetTaskByReportID() { 36 | page := c.Ctx.Input.Query("page") 37 | limit := c.Ctx.Input.Query("limit") 38 | reportid := c.Ctx.Input.Query("report_id") 39 | //cycle := c.Ctx.Input.Query("cycle") 40 | //status := c.Ctx.Input.Query("status") 41 | count, hs, err := models.GetTaskLogList(page, limit, reportid) 42 | if err != nil { 43 | TaskLogRes.Code = 500 44 | TaskLogRes.Message = err.Error() 45 | } else { 46 | TaskLogRes.Code = 200 47 | TaskLogRes.Message = "获取数据成功" 48 | TaskLogRes.Data.Items = hs 49 | TaskLogRes.Data.Total = count 50 | } 51 | c.Data["json"] = TaskLogRes 52 | c.ServeJSON() 53 | } 54 | 55 | // Delete ... 56 | // @Title 删除报表日志 57 | // @Description 删除报表任务 58 | // @Param X-Token header string true "X-Token" 59 | // @Param id path string true "The id you want to delete" 60 | // @Success 200 {string} delete success! 61 | // @Failure 403 id is empty 62 | // @router /:id [delete] 63 | func (c *TaskLogController) Delete() { 64 | idStr := c.Ctx.Input.Param(":id") 65 | id, _ := strconv.Atoi(idStr) 66 | if err := models.DeleteTaskLog(id); err == nil { 67 | ReportRes.Code = 200 68 | ReportRes.Message = "删除成功" 69 | } else { 70 | ReportRes.Code = 500 71 | ReportRes.Message = err.Error() 72 | } 73 | c.Data["json"] = ReportRes 74 | c.ServeJSON() 75 | } 76 | -------------------------------------------------------------------------------- /controllers/template.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | //TemplateController a 8 | type TemplateController struct { 9 | BaseController 10 | } 11 | 12 | //TemplateRes rest 13 | var TemplateRes models.TemplateList 14 | 15 | //URLMapping beego 16 | func (c *TemplateController) URLMapping() { 17 | c.Mapping("Get", c.GetInfo) 18 | c.Mapping("GetALl", c.GetAll) 19 | c.Mapping("GetAllList", c.GetAllList) 20 | c.Mapping("GetItemByTempID", c.GetItemByTempID) 21 | } 22 | 23 | // GetInfo 获取模版 24 | // @Title 获取模版 25 | // @Description 获取模版 26 | // @Param X-Token header string true "x-token in header" 27 | // @Param page query string false "Sorted-by fields. e.g. col1,col2 ..." 28 | // @Param limit query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..." 29 | // @Param templates query string false "Limit the size of result set. Must be an integer" 30 | // @Success 200 {object} models.Manager 31 | // @Failure 403 :id is empty 32 | // @router / [get] 33 | func (c *TemplateController) GetInfo() { 34 | page := c.Ctx.Input.Query("page") 35 | limit := c.Ctx.Input.Query("limit") 36 | templates := c.Ctx.Input.Query("templates") 37 | b, cnt, err := models.TemplateGet(page, limit, templates) 38 | if err != nil { 39 | TemplateRes.Code = 500 40 | TemplateRes.Message = "获取模版错误" 41 | c.Data["json"] = TemplateRes 42 | c.ServeJSON() 43 | return 44 | } 45 | TemplateRes.Code = 200 46 | TemplateRes.Message = "获取成功" 47 | TemplateRes.Data.Items = b 48 | TemplateRes.Data.Total = cnt 49 | c.Data["json"] = TemplateRes 50 | c.ServeJSON() 51 | } 52 | 53 | // GetAll 获取所有模版 54 | // @Title 获取模版 55 | // @Description 获取所有模板列表 56 | // @Param X-Token header string true "x-token in header" 57 | // @Success 200 {object} models.Manager 58 | // @Failure 403 :id is empty 59 | // @router /all [get] 60 | func (c *TemplateController) GetAll() { 61 | b, cnt, err := models.TemplateAllGet() 62 | if err != nil { 63 | TemplateRes.Code = 500 64 | TemplateRes.Message = "获取模版错误" 65 | c.Data["json"] = TemplateRes 66 | c.ServeJSON() 67 | return 68 | } 69 | TemplateRes.Code = 200 70 | TemplateRes.Message = "获取成功" 71 | TemplateRes.Data.Items = b 72 | TemplateRes.Data.Total = cnt 73 | c.Data["json"] = TemplateRes 74 | c.ServeJSON() 75 | } 76 | 77 | // GetAll 获取所有模版 78 | // @Title 获取模版 79 | // @Description 获取所有模板列表 80 | // @Param X-Token header string true "x-token in header" 81 | // @Success 200 {object} models.Manager 82 | // @Failure 403 :id is empty 83 | // @router /list [get] 84 | func (c *TemplateController) GetAllList() { 85 | b, cnt, err := models.TemplateListGet() 86 | if err != nil { 87 | TemplateRes.Code = 500 88 | TemplateRes.Message = "获取模版错误" 89 | } else { 90 | TemplateRes.Code = 200 91 | TemplateRes.Message = "获取成功" 92 | TemplateRes.Data.Items = b 93 | TemplateRes.Data.Total = cnt 94 | } 95 | c.Data["json"] = TemplateRes 96 | c.ServeJSON() 97 | } 98 | 99 | // GetAll 获取所有模版 100 | // @Title 获取模版 101 | // @Description 获取所有模板列表 102 | // @Param X-Token header string true "x-token in header" 103 | // @Param templateid path string ture "templateid" 104 | // @Success 200 {object} models.Manager 105 | // @Failure 403 :id is empty 106 | // @router /item/:templateid [get] 107 | func (c *TemplateController) GetItemByTempID() { 108 | templateid := c.Ctx.Input.Param(":templateid") 109 | b, cnt, err := models.TemplateByItem(templateid) 110 | if err != nil { 111 | TemplateRes.Code = 500 112 | TemplateRes.Message = "获取模版错误" 113 | } else { 114 | TemplateRes.Code = 200 115 | TemplateRes.Message = "获取成功" 116 | TemplateRes.Data.Items = b 117 | TemplateRes.Data.Total = cnt 118 | } 119 | c.Data["json"] = TemplateRes 120 | c.ServeJSON() 121 | } 122 | -------------------------------------------------------------------------------- /controllers/topodata.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/tidwall/gjson" 5 | "zbxtable/models" 6 | ) 7 | 8 | // TopoDataController 绑定数据点 9 | type TopoDataController struct { 10 | BaseController 11 | } 12 | 13 | // URLMapping ... 14 | func (c *TopoDataController) URLMapping() { 15 | c.Mapping("CreateData", c.CreateData) 16 | c.Mapping("GetTopologyOne", c.GetTopologyOne) 17 | //c.Mapping("CreateTopology", c.CreateTopology) 18 | //c.Mapping("InitTopology", c.InitTopology) 19 | } 20 | 21 | // CreateTopology ... 22 | // @Title 创建数据采集点 23 | // @Description 创建数据采集点 24 | // @Param X-Token header string true "X-Token" 25 | // @Param body body models.TopologyData true "body for TopoData content" 26 | // @Success 200 {object} models.TopologyData 27 | // @Failure 403 28 | // @router / [post] 29 | func (c *TopoDataController) CreateData() { 30 | pid := gjson.Get(string(c.Ctx.Input.RequestBody), "pid").String() 31 | vtype := gjson.Get(string(c.Ctx.Input.RequestBody), "v_type").String() 32 | ptype := gjson.Get(string(c.Ctx.Input.RequestBody), "type").String() 33 | tid := gjson.Get(string(c.Ctx.Input.RequestBody), "tid").String() 34 | v := models.TopologyData{PID: pid, Type: ptype, VType: vtype, TID: tid} 35 | _, err := models.AddTopoData(&v) 36 | if err != nil { 37 | TopologyRes.Code = 500 38 | TopologyRes.Message = err.Error() 39 | } else { 40 | TopologyRes.Code = 200 41 | TopologyRes.Message = "创建成功" 42 | } 43 | c.Data["json"] = TopologyRes 44 | c.ServeJSON() 45 | } 46 | 47 | // GetTopologyOne ... 48 | // @Title 获取数据 49 | // @Description 获取数据 50 | // @Param X-Token header string true "X-Token" 51 | // @Param id path string true "id" 52 | // @Success 200 {object} models.Topology 53 | // @Failure 403 54 | // @router /:id [get] 55 | func (c *TopoDataController) GetTopologyOne() { 56 | idStr := c.Ctx.Input.Param(":id") 57 | //id, _ := strconv.Atoi(idStr) 58 | var TopologyRes models.TopologyInfo 59 | //err := models.UpdateEdgedata(id) 60 | //err := models.UpdateNodedata(id) 61 | //if err != nil { 62 | // TopologyRes.Code = 500 63 | // TopologyRes.Message = err.Error() 64 | //} else { 65 | 66 | TopologyRes.Code = 200 67 | TopologyRes.Message = idStr 68 | //} 69 | c.Data["json"] = TopologyRes 70 | c.ServeJSON() 71 | } 72 | -------------------------------------------------------------------------------- /controllers/topology.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/tidwall/gjson" 5 | "strconv" 6 | "zbxtable/models" 7 | ) 8 | 9 | // TopologyController 拓扑图 10 | type TopologyController struct { 11 | BaseController 12 | } 13 | 14 | //TopologyRes is used 15 | var TopologyRes models.TopologyList 16 | 17 | // URLMapping ... 18 | func (c *TopologyController) URLMapping() { 19 | c.Mapping("GetTopologyAll", c.GetTopologyAll) 20 | c.Mapping("GetTopologyOne", c.GetTopologyOne) 21 | c.Mapping("CreateTopology", c.CreateTopology) 22 | c.Mapping("Delete", c.Delete) 23 | c.Mapping("Put", c.Put) 24 | c.Mapping("DeployTopology", c.DeployTopology) 25 | } 26 | 27 | // GetTopologyAll ... 28 | // @Title 获取拓扑列表 29 | // @Description 获取拓扑列表 30 | // @Param X-Token header string true "X-Token" 31 | // @Param page query string false "页数" 32 | // @Param limit query string false "每页数" 33 | // @Param name query string false "拓扑名称" 34 | // @Success 200 {object} models.Topology 35 | // @Failure 403 36 | // @router / [get] 37 | func (c *TopologyController) GetTopologyAll() { 38 | page := c.Ctx.Input.Query("page") 39 | limit := c.Ctx.Input.Query("limit") 40 | name := c.Ctx.Input.Query("name") 41 | count, hs, err := models.GetAllTopology(page, limit, name) 42 | if err != nil { 43 | TopologyRes.Code = 500 44 | TopologyRes.Message = err.Error() 45 | } else { 46 | TopologyRes.Code = 200 47 | TopologyRes.Message = "获取数据成功" 48 | TopologyRes.Data.Items = hs 49 | TopologyRes.Data.Total = count 50 | } 51 | c.Data["json"] = TopologyRes 52 | c.ServeJSON() 53 | } 54 | 55 | // GetTopologyOne ... 56 | // @Title 获取拓扑详情 57 | // @Description 获取拓扑详情 58 | // @Param X-Token header string true "X-Token" 59 | // @Param id path string true "id" 60 | // @Success 200 {object} models.Topology 61 | // @Failure 403 62 | // @router /:id [get] 63 | func (c *TopologyController) GetTopologyOne() { 64 | idStr := c.Ctx.Input.Param(":id") 65 | id, _ := strconv.Atoi(idStr) 66 | var TopologyResp models.TopologyInfo 67 | v, err := models.GetTopologyById(id) 68 | if err != nil { 69 | TopologyResp.Code = 500 70 | TopologyResp.Message = err.Error() 71 | } else { 72 | TopologyResp.Code = 200 73 | TopologyResp.Message = "获取成功" 74 | TopologyResp.Data.Items = v 75 | } 76 | c.Data["json"] = TopologyResp 77 | c.ServeJSON() 78 | } 79 | 80 | // CreateTopology ... 81 | // @Title 创建拓扑图 82 | // @Description 创建拓扑图 83 | // @Param X-Token header string true "X-Token" 84 | // @Param body body models.Topology true "body for Topology content" 85 | // @Success 200 {object} models.Topology 86 | // @Failure 403 87 | // @router / [post] 88 | func (c *TopologyController) CreateTopology() { 89 | nodes := gjson.Get(string(c.Ctx.Input.RequestBody), "nodes").String() 90 | edges := gjson.Get(string(c.Ctx.Input.RequestBody), "edges").String() 91 | topology := gjson.Get(string(c.Ctx.Input.RequestBody), "topology").String() 92 | v := models.Topology{Nodes: nodes, Edges: edges, Topology: topology} 93 | _, err := models.AddTopology(&v) 94 | if err != nil { 95 | TopologyRes.Code = 500 96 | TopologyRes.Message = err.Error() 97 | } else { 98 | TopologyRes.Code = 200 99 | TopologyRes.Message = "创建成功" 100 | } 101 | c.Data["json"] = TopologyRes 102 | c.ServeJSON() 103 | } 104 | 105 | // DeployTopology ... 106 | // @Title 发布拓扑 107 | // @Description 发布拓扑 108 | // @Param X-Token header string true "X-Token" 109 | // @Param body body models.Topology true "body for Topology content" 110 | // @Success 200 {object} models.Topology 111 | // @Failure 403 112 | // @router /deploy [post] 113 | func (c *TopologyController) DeployTopology() { 114 | idStr := gjson.Get(string(c.Ctx.Input.RequestBody), "id").String() 115 | id, _ := strconv.Atoi(idStr) 116 | v := models.Topology{ID: id} 117 | 118 | err := models.UpdateTopologyStatusByID(&v) 119 | if err != nil { 120 | TopologyRes.Code = 500 121 | TopologyRes.Message = err.Error() 122 | } else { 123 | TopologyRes.Code = 200 124 | TopologyRes.Message = "更新成功" 125 | } 126 | TopologyRes.Data.Items = []models.Topology{} 127 | c.Data["json"] = TopologyRes 128 | c.ServeJSON() 129 | } 130 | 131 | // saveTopology.. 132 | // @Title 更新拓扑图 133 | // @Description 更新拓扑图 134 | // @Param X-Token header string true "X-Token" 135 | // @Param body body models.Topology true "body for Topology content" 136 | // @Success 200 {object} models.Topology 137 | // @Failure 403 138 | // @router / [put] 139 | func (c *TopologyController) Put() { 140 | idStr := c.Ctx.Input.Param(":id") 141 | id, _ := strconv.Atoi(idStr) 142 | v := models.Topology{ID: id} 143 | if err := json.Unmarshal(c.Ctx.Input.RequestBody, &v); err == nil { 144 | if err := models.UpdateTopologyByID(&v); err == nil { 145 | TopologyRes.Code = 200 146 | TopologyRes.Message = "保存成功" 147 | c.Data["json"] = "OK" 148 | } else { 149 | TopologyRes.Code = 500 150 | TopologyRes.Message = err.Error() 151 | } 152 | } else { 153 | TopologyRes.Code = 500 154 | TopologyRes.Message = err.Error() 155 | } 156 | c.Data["json"] = TopologyRes 157 | c.ServeJSON() 158 | } 159 | 160 | // Delete ... 161 | // @Title 删除拓扑图 162 | // @Description 删除拓扑图 163 | // @Param X-Token header string true "X-Token" 164 | // @Param id path string true "The id you want to delete" 165 | // @Success 200 {string} delete success! 166 | // @Failure 403 id is empty 167 | // @router /:id [delete] 168 | func (c *TopologyController) Delete() { 169 | idStr := c.Ctx.Input.Param(":id") 170 | id, _ := strconv.Atoi(idStr) 171 | if err := models.DeleteTopology(id); err == nil { 172 | TopologyRes.Code = 200 173 | TopologyRes.Message = "删除成功" 174 | } else { 175 | TopologyRes.Code = 500 176 | TopologyRes.Message = err.Error() 177 | } 178 | c.Data["json"] = TopologyRes 179 | c.ServeJSON() 180 | } 181 | -------------------------------------------------------------------------------- /controllers/trend.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | // TrendController operations for Trend 8 | type TrendController struct { 9 | BaseController 10 | } 11 | 12 | //TrendRes resp 13 | var TrendRes models.TrendList 14 | 15 | // URLMapping ... 16 | func (c *TrendController) URLMapping() { 17 | c.Mapping("GetTrendByItemID", c.GetTrendByItemID) 18 | } 19 | 20 | // GetTrendByItemID controller 21 | // @Title Get One 22 | // @Description get item by key 23 | // @Param X-Token header string true "x-token in header" 24 | // @Param item_id query string true "The key for item" 25 | // @Param limit query string true "The key for item" 26 | // @Success 200 {object} models.Item 27 | // @Failure 403 :id is empty 28 | // @router / [get] 29 | func (c *TrendController) GetTrendByItemID() { 30 | itemID := c.Ctx.Input.Query("item_id") 31 | limit := c.Ctx.Input.Query("limit") 32 | v, err := models.GetTrendByItemID(itemID, limit) 33 | if err != nil { 34 | c.Data["json"] = err.Error() 35 | } else { 36 | c.Data["json"] = v 37 | } 38 | c.ServeJSON() 39 | } 40 | -------------------------------------------------------------------------------- /controllers/trigger.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "zbxtable/models" 5 | ) 6 | 7 | //TriggersController funct 8 | type TriggersController struct { 9 | BaseController 10 | } 11 | 12 | //TriggersRes resp 13 | var TriggersRes models.TriggersRes 14 | var TriggersListRes models.TriggersListRes 15 | 16 | //URLMapping beego 17 | func (c *TriggersController) URLMapping() { 18 | c.Mapping("Get", c.GetInfo) 19 | c.Mapping("GetOne", c.GetOne) 20 | } 21 | 22 | // GetInfo 获取未恢复告警 23 | // @Title 获取未恢复告警据 24 | // @Description 获取未恢复告警 25 | // @Param X-Token header string true "x-token in header" 26 | // @Success 200 {object} models.Triggers 27 | // @Failure 403 :id is empty 28 | // @router / [get] 29 | func (c *TriggersController) GetInfo() { 30 | b, cnt, err := models.GetTriggers() 31 | if err != nil { 32 | TriggersRes.Code = 500 33 | TriggersRes.Message = err.Error() 34 | } else { 35 | TriggersRes.Code = 200 36 | TriggersRes.Message = "获取成功" 37 | TriggersRes.Data.Items = b 38 | TriggersRes.Data.Total = cnt 39 | } 40 | c.Data["json"] = TriggersRes 41 | c.ServeJSON() 42 | } 43 | 44 | // GetOne 根据主机ID获取Trigger列表 45 | // @Title 根据主机ID获取Trigger列表, 46 | // @Description 根据主机ID获取Trigger列表 47 | // @Param X-Token header string true "x-token in header"\ 48 | // @Param hostid query string true "hostid" 49 | // @Success 200 {object} models.Triggers 50 | // @Failure 403 :id is empty 51 | // @router /list [get] 52 | func (c *TriggersController) GetOne() { 53 | HostID := c.Ctx.Input.Query("hostid") 54 | b, cnt, err := models.GetTriggerList(HostID) 55 | if err != nil { 56 | TriggersListRes.Code = 500 57 | TriggersListRes.Message = err.Error() 58 | } else { 59 | TriggersListRes.Code = 200 60 | TriggersListRes.Message = "获取成功" 61 | TriggersListRes.Data.Items = b 62 | TriggersListRes.Data.Total = cnt 63 | } 64 | c.Data["json"] = TriggersListRes 65 | c.ServeJSON() 66 | } 67 | -------------------------------------------------------------------------------- /controllers/websocket.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/logs" 6 | "github.com/gorilla/websocket" 7 | "net/http" 8 | "strconv" 9 | "time" 10 | "zbxtable/models" 11 | ) 12 | 13 | type WebSocketController struct { 14 | beego.Controller 15 | } 16 | 17 | var wsUpgrader = websocket.Upgrader{ 18 | ReadBufferSize: 1024, 19 | WriteBufferSize: 1024, 20 | HandshakeTimeout: 10 * time.Second, 21 | CheckOrigin: func(r *http.Request) bool { 22 | return true 23 | }, 24 | } 25 | 26 | func (c *WebSocketController) Get() { 27 | idStr := c.Ctx.Input.Param(":id") 28 | id, _ := strconv.Atoi(idStr) 29 | ws, err := wsUpgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil) 30 | if _, ok := err.(websocket.HandshakeError); ok { 31 | http.Error(c.Ctx.ResponseWriter, "Not a websocket handshake", 400) 32 | return 33 | } else if err != nil { 34 | logs.Error("Cannot setup WebSocket connection:", err) 35 | return 36 | } 37 | defer ws.Close() 38 | for { 39 | //读取数据 40 | _, ms, err := ws.ReadMessage() 41 | if err != nil { 42 | logs.Debug(err) 43 | break 44 | } 45 | //发送数据 46 | if string(ms) == "success" { 47 | //查询数据 48 | val, err := models.GetTopologyById(id) 49 | if err != nil { 50 | logs.Debug(err) 51 | continue 52 | } 53 | //write 54 | msg, _ := json.Marshal(val) 55 | err = ws.WriteMessage(websocket.TextMessage, msg) 56 | if err != nil { 57 | logs.Debug(err) 58 | continue 59 | } 60 | //更新数据 61 | err = models.UpdateEdgeDataById(id) 62 | if err != nil { 63 | continue 64 | } 65 | 66 | } 67 | time.Sleep(time.Second * 10) 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module zbxtable 2 | 3 | go 1.21 4 | 5 | toolchain go1.21.4 6 | 7 | require ( 8 | github.com/360EntSecGroup-Skylar/excelize v1.4.1 9 | github.com/Knetic/govaluate v3.0.0+incompatible 10 | github.com/astaxie/beego v1.12.3 11 | github.com/canghai908/jwt-beego v0.0.0-20210814140549-930145f4313e 12 | github.com/canghai908/zabbix-go v0.0.0-20250224122310-404074f2f28a 13 | github.com/go-echarts/go-echarts/v2 v2.2.5 14 | github.com/go-redis/redis/v8 v8.11.5 15 | github.com/go-sql-driver/mysql v1.7.0 16 | github.com/google/uuid v1.3.0 17 | github.com/gorilla/websocket v1.5.0 18 | github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible 19 | github.com/json-iterator/go v1.1.12 20 | github.com/lib/pq v1.10.7 21 | github.com/manifoldco/promptui v0.9.0 22 | github.com/pterm/pterm v0.12.75 23 | github.com/sanbornm/go-selfupdate v0.0.0-20210106163404-c9b625feac49 24 | github.com/shopspring/decimal v1.3.1 25 | github.com/signintech/gopdf v0.16.1 26 | github.com/tidwall/gjson v1.14.4 27 | github.com/urfave/cli/v2 v2.25.0 28 | github.com/xen0n/go-workwx v1.3.1 29 | github.com/xuri/excelize/v2 v2.4.1 30 | golang.org/x/crypto v0.7.0 31 | gopkg.in/ini.v1 v1.67.0 32 | ) 33 | 34 | require ( 35 | atomicgo.dev/cursor v0.2.0 // indirect 36 | atomicgo.dev/keyboard v0.2.9 // indirect 37 | atomicgo.dev/schedule v0.1.0 // indirect 38 | github.com/beorn7/perks v1.0.1 // indirect 39 | github.com/canghai908/reflector v0.0.0-20230322064147-12d37cdd08b2 // indirect 40 | github.com/cenkalti/backoff/v4 v4.1.3 // indirect 41 | github.com/cespare/xxhash/v2 v2.1.2 // indirect 42 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect 43 | github.com/containerd/console v1.0.3 // indirect 44 | github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect 45 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 46 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect 47 | github.com/golang/protobuf v1.4.2 // indirect 48 | github.com/gookit/color v1.5.4 // indirect 49 | github.com/hashicorp/golang-lru v0.5.4 // indirect 50 | github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect 51 | github.com/kr/binarydist v0.1.0 // indirect 52 | github.com/lithammer/fuzzysearch v1.1.8 // indirect 53 | github.com/mattn/go-runewidth v0.0.15 // indirect 54 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 55 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 56 | github.com/modern-go/reflect2 v1.0.2 // indirect 57 | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect 58 | github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect 59 | github.com/pkg/errors v0.9.1 // indirect 60 | github.com/prometheus/client_golang v1.7.0 // indirect 61 | github.com/prometheus/client_model v0.2.0 // indirect 62 | github.com/prometheus/common v0.10.0 // indirect 63 | github.com/prometheus/procfs v0.1.3 // indirect 64 | github.com/richardlehane/mscfb v1.0.4 // indirect 65 | github.com/richardlehane/msoleps v1.0.3 // indirect 66 | github.com/rivo/uniseg v0.4.4 // indirect 67 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 68 | github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect 69 | github.com/tidwall/match v1.1.1 // indirect 70 | github.com/tidwall/pretty v1.2.0 // indirect 71 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect 72 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect 73 | github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect 74 | golang.org/x/net v0.8.0 // indirect 75 | golang.org/x/sys v0.16.0 // indirect 76 | golang.org/x/term v0.16.0 // indirect 77 | golang.org/x/text v0.14.0 // indirect 78 | google.golang.org/protobuf v1.23.0 // indirect 79 | gopkg.in/inconshreveable/go-update.v0 v0.0.0-20150814200126-d8b0b1d421aa // indirect 80 | gopkg.in/yaml.v2 v2.4.0 // indirect 81 | ) 82 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | //go:generate go-bindata -o=packfile/staticFile.go -pkg=packfile ./web/... ./template/... ./conf/... 2 | package main 3 | 4 | import ( 5 | "fmt" 6 | "github.com/json-iterator/go/extra" 7 | "github.com/urfave/cli/v2" 8 | "os" 9 | "path/filepath" 10 | "zbxtable/cmd" 11 | ) 12 | 13 | // AppVersion version 14 | // 15 | 16 | var ( 17 | version = "No Version Provided" 18 | gitHash = "No GitHash Provided" 19 | buildTime = "No BuildTime Provided" 20 | ) 21 | 22 | func customVersionPrinter(c *cli.Context) { 23 | fmt.Printf("%v Version:=%v\nGit Commit Hash:=%v\nUTC Build Time:=%v\n", filepath.Base(c.App.Name), 24 | version, gitHash, buildTime) 25 | } 26 | func init() { 27 | // RegisterFuzzyDecoders decode input from PHP with tolerance. 28 | extra.RegisterFuzzyDecoders() 29 | } 30 | 31 | func main() { 32 | app := cli.NewApp() 33 | app.Name = "ZbxTable" 34 | app.Usage = "A Zabbix Table tools" 35 | cli.VersionPrinter = customVersionPrinter 36 | cmd.GetVersion(version, gitHash, buildTime) 37 | app.Version = version 38 | app.Commands = []*cli.Command{ 39 | cmd.Web, 40 | cmd.Install, 41 | cmd.Update, 42 | //cmd.Init, 43 | cmd.Uninstall, 44 | } 45 | app.Run(os.Args) 46 | } 47 | -------------------------------------------------------------------------------- /models/alarm.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "github.com/astaxie/beego/orm" 8 | ) 9 | 10 | // TableName alarm 11 | func (t *Alarm) TableName() string { 12 | return TableName("alarm") 13 | } 14 | 15 | // AddAlarm insert a new Alarm into database and returns 16 | // last inserted Id on success. 17 | func AddAlarm(m *Alarm) (id int64, err error) { 18 | o := orm.NewOrm() 19 | id, err = o.Insert(m) 20 | if err != nil { 21 | return 0, err 22 | } 23 | return id, nil 24 | } 25 | 26 | // //update alarm notifystatus 27 | func UpdateAlarmStatus(m *Alarm) (id int64, err error) { 28 | o := orm.NewOrm() 29 | //user 30 | v := Alarm{ID: m.ID} 31 | err = o.Read(&v) 32 | if err != nil { 33 | return 0, err 34 | } 35 | v.NotifyStatus = m.NotifyStatus 36 | id, err = o.Update(m, "NotifyStatus") 37 | if err != nil { 38 | return 0, err 39 | } 40 | return id, nil 41 | } 42 | 43 | // GetAlarmByID retrieves Alarm by Id. Returns error if 44 | // Id doesn't exist 45 | func GetAlarmByID(id int) (v *Alarm, err error) { 46 | o := orm.NewOrm() 47 | v = &Alarm{ID: id} 48 | if err = o.Read(v); err == nil { 49 | return v, nil 50 | } 51 | return nil, err 52 | } 53 | 54 | // GetAllAlarm retrieves all Alarm matches certain condition. Returns empty list if 55 | // no records exist 56 | func GetAllAlarm(begin, end time.Time, page, limit, hosts, ip, tenant_id, status, level string) (cnt int64, al []Alarm, err error) { 57 | o := orm.NewOrm() 58 | var alarms []Alarm 59 | var CountAlarms []Alarm 60 | qs := o.QueryTable(new(Alarm)) 61 | pages, _ := strconv.Atoi(page) 62 | limits, _ := strconv.Atoi(limit) 63 | 64 | //count alarms 65 | cond := orm.NewCondition() 66 | if hosts != "" { 67 | cond = cond.And("host__icontains", hosts) 68 | } 69 | if tenant_id != "" { 70 | cond = cond.And("tenant_id", tenant_id) 71 | } 72 | if status != "" { 73 | cond = cond.And("status", status) 74 | } 75 | if level != "" { 76 | cond = cond.And("level", level) 77 | } 78 | if ip != "" { 79 | cond = cond.And("host_ip__icontains", ip) 80 | } 81 | 82 | qs = qs.Filter("occurtime__gte", begin).Filter("occurtime__lte", end).SetCond(cond) 83 | 84 | // 获取总数 85 | cnt, err = qs.All(&CountAlarms) 86 | if err != nil { 87 | return 0, []Alarm{}, err 88 | } 89 | 90 | // 获取分页数据 91 | _, err = qs.Limit(limits, (pages-1)*limits).OrderBy("-occurtime").All(&alarms) 92 | if err != nil { 93 | return 0, []Alarm{}, err 94 | } 95 | 96 | return cnt, alarms, nil 97 | } 98 | 99 | // get alarm tenant list 100 | func GetAlarmTenant() (cnt int64, data interface{}, err error) { 101 | o := orm.NewOrm() 102 | var maps []orm.Params 103 | num, err := o.Raw("select distinct zbxtable_alarm.tenant_id from zbxtable_alarm;").Values(&maps) 104 | if err != nil { 105 | return 0, []Alarm{}, err 106 | } 107 | type list struct { 108 | ID int `json:"id"` 109 | TenantID string `json:"tenant_id"` 110 | } 111 | var ss []list 112 | var p list 113 | if num > 0 { 114 | for i := 0; i < len(maps); i++ { 115 | p.ID = i 116 | p.TenantID = maps[i]["tenant_id"].(string) 117 | ss = append(ss, p) 118 | } 119 | } 120 | return num, ss, nil 121 | } 122 | 123 | // ExportAlarm export 124 | func ExportAlarm(begin, end time.Time, 125 | hosts, tenant_id, status, level string) ([]byte, error) { 126 | o := orm.NewOrm() 127 | var alarms []Alarm 128 | al := new(Alarm) 129 | intbegin := begin.Unix() 130 | intend := end.Unix() 131 | //count alarms 132 | cond := orm.NewCondition() 133 | if hosts != "" { 134 | cond = cond.And("host__icontains", hosts) 135 | } 136 | if tenant_id != "" { 137 | cond = cond.And("tenant_id", tenant_id) 138 | } 139 | if status != "" { 140 | cond = cond.And("status", status) 141 | } 142 | if level != "" { 143 | cond = cond.And("level", level) 144 | } 145 | _, err := o.QueryTable(al).Filter("occurtime__gte", begin).Filter("occurtime__lte", end). 146 | SetCond(cond). 147 | OrderBy("-occurtime").All(&alarms) 148 | if err != nil { 149 | return []byte{}, err 150 | } 151 | cnt := int64(len(alarms)) 152 | pbye, err := CreateAlarmXlsx(alarms, cnt, intbegin, intend) 153 | if err != nil { 154 | return []byte{}, err 155 | } 156 | return pbye, nil 157 | } 158 | 159 | // AnalysisAlarm all alarm 160 | func AnalysisAlarm(begin, end time.Time, tenant_id string) (arrytile []string, pie []Pie, na []string, va []int, err error) { 161 | o := orm.NewOrm() 162 | strbeing := begin.Format("2006-01-02 15:04:05") 163 | strend := end.Format("2006-01-02 15:04:05") 164 | var maps []orm.Params 165 | var ss []string 166 | dpie := []Pie{} 167 | //饼图数据 168 | var num int64 169 | 170 | baseQueryPie := "SELECT level, COUNT(DISTINCT id) AS level_count " + 171 | "FROM zbxtable_alarm WHERE occurtime >= ? AND occurtime <= ? " + 172 | "AND (STATUS='故障' or STATUS='1') " 173 | 174 | var paramsPie []interface{} 175 | paramsPie = append(paramsPie, strbeing, strend) 176 | 177 | if tenant_id != "" { 178 | baseQueryPie += "AND tenant_id = ? " 179 | paramsPie = append(paramsPie, tenant_id) 180 | } 181 | 182 | baseQueryPie += "GROUP BY level ORDER BY level_count DESC" 183 | 184 | num, err = o.Raw(baseQueryPie, paramsPie...).Values(&maps) 185 | 186 | if err == nil && num > 0 { 187 | for i := 0; i < len(maps); i++ { 188 | ss = append(ss, maps[i]["level"].(string)) 189 | va, _ := strconv.Atoi(maps[i]["level_count"].(string)) 190 | n := Pie{Value: va, Name: maps[i]["level"].(string)} 191 | dpie = append(dpie, n) 192 | } 193 | } 194 | 195 | //修改top10数据查询 196 | var map1s []orm.Params 197 | var name []string 198 | var values []int 199 | 200 | baseQuery := "SELECT host, hostname, COUNT(DISTINCT id) AS host_count " + 201 | "FROM zbxtable_alarm WHERE occurtime >= ? AND occurtime <= ? " + 202 | "AND (STATUS='故障' or STATUS='1') " 203 | 204 | var params []interface{} 205 | params = append(params, strbeing, strend) 206 | 207 | if tenant_id != "" { 208 | baseQuery += "AND tenant_id = ? " 209 | params = append(params, tenant_id) 210 | } 211 | 212 | // 修改排序,确保按照告警数量降序排列 213 | baseQuery += "GROUP BY host, hostname ORDER BY COUNT(DISTINCT id) DESC LIMIT 10" 214 | 215 | _, err = o.Raw(baseQuery, params...).Values(&map1s) 216 | 217 | if err == nil && len(map1s) > 0 { 218 | for i := 0; i < len(map1s); i++ { 219 | name = append(name, map1s[i]["hostname"].(string)) 220 | va, _ := strconv.Atoi(map1s[i]["host_count"].(string)) 221 | values = append(values, va) 222 | } 223 | } 224 | 225 | return ss, dpie, name, values, nil 226 | } 227 | -------------------------------------------------------------------------------- /models/alarm_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | const ( 6 | NotifySuccess = iota // 0 7 | NotifyMuted // 1 8 | NotifyDefault // 2 9 | ) 10 | 11 | //Alarm struct 12 | type Alarm struct { 13 | ID int `orm:"column(id);auto" json:"id"` 14 | //v2 add begin 15 | TenantID string `orm:"column(tenant_id);size(255)" json:"tenant_id"` 16 | HostID string `orm:"column(host_id);size(255)" json:"host_id"` 17 | Hostname string `orm:"column(hostname);size(255)" json:"hostname"` 18 | Host string `orm:"column(host);size(200)" json:"host"` 19 | HostsIP string `orm:"column(host_ip);size(200)" json:"host_ip"` 20 | TriggerID int64 `orm:"column(trigger_id);size(200)" json:"trigger_id"` 21 | ItemID int64 `orm:"column(item_id);size(200)" json:"item_id"` 22 | ItemName string `orm:"column(item_name);type(text)" json:"item_name"` 23 | ItemValue string `orm:"column(item_value);type(text)" json:"item_value"` 24 | Hgroup string `orm:"column(hgroup);size(200)" json:"hgroup"` 25 | OccurTime time.Time `orm:"column(occurtime);type(datetime)" json:"occur_time"` 26 | Level string `orm:"column(level);size(200)" json:"level"` 27 | Message string `orm:"column(message);type(text)" json:"message"` 28 | Hkey string `orm:"column(hkey);size(3000)" json:"hkey"` 29 | Detail string `orm:"column(detail);type(text)" json:"detail"` 30 | EventID int64 `orm:"column(event_id);size(200)" json:"eventid"` 31 | EventDuration string `orm:"column(event_duration);size(50)" json:"event_duration"` 32 | Status string `orm:"column(status);size(200)" json:"status"` 33 | NotifyStatus string `orm:"column(notify_status);size(10)" json:"notify_status"` 34 | } 35 | 36 | //ListQueryAlarm query 37 | type ListQueryAlarm struct { 38 | Host string `json:"host"` 39 | Period []string `json:"period"` 40 | } 41 | 42 | //ListExportAlarm struct 43 | type ListExportAlarm struct { 44 | Begin string `json:"begin"` 45 | End string `json:"end"` 46 | Hosts string `json:"hosts"` 47 | TenantID string `json:"tenant_id"` 48 | Status string `json:"status"` 49 | Level string `json:"level"` 50 | } 51 | 52 | //ListAnalysisAlarm qu 53 | type ListAnalysisAlarm struct { 54 | Begin string `json:"begin"` 55 | End string `json:"end"` 56 | TenantID string `json:"tenant_id"` 57 | } 58 | 59 | //Pie struct 60 | type Pie struct { 61 | Value int `json:"value"` 62 | Name string `json:"name"` 63 | } 64 | 65 | //AlarmList struct 66 | type AlarmList struct { 67 | Code int `json:"code"` 68 | Message string `json:"message"` 69 | Data struct { 70 | Items []Alarm `json:"items"` 71 | Total int64 `json:"total"` 72 | } `json:"data"` 73 | } 74 | 75 | //AlarmList struct 76 | type AlarmTendantList struct { 77 | Code int `json:"code"` 78 | Message string `json:"message"` 79 | Data struct { 80 | Items interface{} `json:"items"` 81 | Total int64 `json:"total"` 82 | } `json:"data"` 83 | } 84 | 85 | //AnalysisList struct 86 | type AnalysisList struct { 87 | Code int `json:"code"` 88 | Message string `json:"message"` 89 | Data struct { 90 | Level []string `json:"level"` 91 | LevelCount []Pie `json:"level_count"` 92 | Host []string `json:"host"` 93 | HostCount []int `json:"host_count"` 94 | } `json:"data"` 95 | } 96 | -------------------------------------------------------------------------------- /models/application.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | ) 6 | 7 | //GetApplicationByHostid st 8 | func GetApplicationByHostid(hostid string) ([]Application, int64, error) { 9 | exp := []string{"applicationid", "name"} 10 | output := []string{"itemid", "name", "value_type", "units"} 11 | rep, err := API.Call("application.get", Params{"output": exp, 12 | "hostids": hostid, "selectItems": output}) 13 | if err != nil { 14 | return []Application{}, 0, err 15 | } 16 | //log.Println(rep.Result) 17 | hba, err := json.Marshal(rep.Result) 18 | if err != nil { 19 | logs.Error(err) 20 | return []Application{}, 0, err 21 | } 22 | 23 | var hb []Application 24 | err = json.Unmarshal(hba, &hb) 25 | if err != nil { 26 | logs.Error(err) 27 | return []Application{}, 0, err 28 | } 29 | return hb, int64(len(hb)), err 30 | } 31 | -------------------------------------------------------------------------------- /models/application_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // ApplicationList struct 4 | type ApplicationList struct { 5 | Code int `json:"code"` 6 | Message string `json:"mess age"` 7 | Data struct { 8 | Items []Application `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | // Application struct 14 | type Application struct { 15 | Applicationid string `json:"applicationid"` 16 | Name string `json:"name"` 17 | Items []ApplicationItem `json:"items"` 18 | } 19 | 20 | // ApplicationItem struct 21 | type ApplicationItem struct { 22 | ItemID string `json:"itemid"` 23 | Name string `json:"name"` 24 | ValutType string `json:"value_type"` 25 | Units string `json:"units"` 26 | } 27 | 28 | type MonIts struct { 29 | Itemid string `json:"itemid"` 30 | Key string `json:"key_"` 31 | Lastclock string `json:"lastclock"` 32 | Lastvalue string `json:"lastvalue"` 33 | Name string `json:"name"` 34 | Tags []struct { 35 | Tag string `json:"tag"` 36 | Value string `json:"value"` 37 | } `json:"tags"` 38 | SNMPOid string `json:"snmp_oid"` 39 | Trends string `json:"trends"` 40 | Units string `json:"units"` 41 | ValueType string `json:"value_type"` 42 | Delay string `json:"delay"` 43 | ValuemapID string `json:"valuemapid"` 44 | } 45 | 46 | // Application struct 47 | type TagsItems struct { 48 | Name string `json:"name"` 49 | Items []MonIts `json:"items"` 50 | } 51 | -------------------------------------------------------------------------------- /models/before.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | "strings" 6 | "zbxtable/utils" 7 | ) 8 | 9 | func MsAdd(tenantid string, message []byte) (int64, error) { 10 | //replace " \ 11 | p0 := strings.Replace(string(message), `\`, `\\`, -1) 12 | p1 := strings.Replace(p0, `"`, `\"`, -1) 13 | p2 := strings.ReplaceAll(p1, `¦`, `"`) 14 | var mes EventTpl 15 | err := json.Unmarshal([]byte(p2), &mes) 16 | if err != nil { 17 | logs.Error(err) 18 | return 0, err 19 | } 20 | occurTime, err := utils.ParTime(mes.EventTime) 21 | if err != nil { 22 | logs.Error(err) 23 | return 0, err 24 | } 25 | var meal = Alarm{ 26 | TenantID: tenantid, 27 | HostID: mes.HostsID, 28 | Hostname: mes.Hostname, 29 | Host: mes.HostHost, 30 | HostsIP: mes.HostsIP, 31 | TriggerID: mes.TriggerID, 32 | ItemID: mes.ItemID, 33 | ItemName: mes.ItemName, 34 | ItemValue: mes.ItemValue, 35 | Hgroup: mes.HostGroup, 36 | OccurTime: occurTime, 37 | Level: mes.Severity, 38 | Message: mes.TriggerName, 39 | Hkey: mes.TriggerKey, 40 | Detail: mes.ItemName + ":" + mes.ItemValue, 41 | Status: mes.TriggerValue, 42 | EventID: mes.EventID, 43 | EventDuration: mes.EventDuration, 44 | } 45 | id, err := AddAlarm(&meal) 46 | if err != nil { 47 | logs.Error(err) 48 | return 0, err 49 | } 50 | //alert gen 51 | GenAlert(&meal) 52 | return id, nil 53 | } 54 | -------------------------------------------------------------------------------- /models/config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/orm" 5 | "time" 6 | ) 7 | 8 | // TableName alarm 9 | func (t *Config) TableName() string { 10 | return TableName("config") 11 | } 12 | 13 | type Config struct { 14 | ID int64 `orm:"column(id);auto" json:"id"` 15 | Name string `orm:"column(name);size(255)" json:"name"` 16 | Key string `orm:"column(key);size(255)" json:"key"` 17 | Value string `orm:"column(value);size(255)" json:"value"` 18 | Comment string `orm:"column(comment);size(255)" json:"comment"` 19 | CreatedAt time.Time `orm:"column(created_at);type(datetime);auto_now_add" json:"created_at"` 20 | UpdatedAt time.Time `orm:"column(updated_at);type(datetime);auto_now" json:"updated_at"` 21 | } 22 | 23 | // GetConfigList 获取系统配置 24 | func GetConfigList() ([]Config, error) { 25 | o := orm.NewOrm() 26 | var v []Config 27 | _, err := o.QueryTable(Config{}).OrderBy("ID").All(&v) 28 | if err != nil { 29 | return nil, err 30 | } 31 | return v, err 32 | } 33 | 34 | // GetConfigOne 获取某一个配置 35 | func GetConfigOne(id int64) (v *Config, err error) { 36 | o := orm.NewOrm() 37 | v = &Config{ID: id} 38 | if err = o.Read(v); err == nil { 39 | return v, nil 40 | } 41 | return nil, err 42 | } 43 | 44 | // UpdateConfig 更新系统配置 45 | func UpdateConfig(m *Config) (err error) { 46 | o := orm.NewOrm() 47 | v := Config{ID: m.ID} 48 | //数据面板独立配置 49 | err = o.Read(&v) 50 | if err != nil { 51 | return err 52 | } 53 | v.Value = m.Value 54 | _, err = o.Update(m, "Value") 55 | if err != nil { 56 | return err 57 | } 58 | //dash处理 59 | if m.ID == 1 { 60 | err = updateZbxDash(m) 61 | if err != nil { 62 | return err 63 | } 64 | return nil 65 | } 66 | return nil 67 | } 68 | 69 | // 数据面板控制 70 | func updateZbxDash(m *Config) (err error) { 71 | o := orm.NewOrm() 72 | menu := Menu{Router: "dash"} 73 | if o.Read(&menu, "Router") == nil { 74 | switch m.Value { 75 | case "0": 76 | menu.IsAvailable = true 77 | case "1": 78 | menu.IsAvailable = false 79 | } 80 | } 81 | _, err = o.Update(&menu, "IsAvailable") 82 | if err != nil { 83 | return err 84 | } 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /models/cron_init.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | var ( 4 | //IMWorkerChan chan int 5 | WechatWorkerChan chan int 6 | MailWorkerChan chan int 7 | ) 8 | 9 | func InitSenderWorker() { 10 | MailWorkerChan = make(chan int, 2) 11 | WechatWorkerChan = make(chan int, 2) 12 | } 13 | -------------------------------------------------------------------------------- /models/cron_mail.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "crypto/tls" 7 | "fmt" 8 | "html/template" 9 | "net/smtp" 10 | "strconv" 11 | "strings" 12 | "time" 13 | template2 "zbxtable/utils" 14 | 15 | "github.com/astaxie/beego" 16 | "github.com/astaxie/beego/logs" 17 | "github.com/astaxie/beego/orm" 18 | redis "github.com/go-redis/redis/v8" 19 | "github.com/jordan-wright/email" 20 | ) 21 | 22 | // copy from open-facon-plus 23 | func ConsumeMail() { 24 | for { 25 | L := PopAllMail() 26 | if len(L) == 0 { 27 | time.Sleep(time.Millisecond * 200) 28 | continue 29 | } 30 | SendMailList(L) 31 | } 32 | } 33 | func SendMailList(L []*Event) { 34 | for _, mail := range L { 35 | MailWorkerChan <- 1 36 | go SendMail(mail) 37 | } 38 | } 39 | 40 | func SendMail(mail *Event) { 41 | defer func() { 42 | <-MailWorkerChan 43 | }() 44 | o := orm.NewOrm() 45 | ids := strings.Split(mail.ToUsers, ",") 46 | var user Manager 47 | var plist []Manager 48 | _, err := o.QueryTable(user).Filter("id__in", ids). 49 | All(&plist, "id", "username", "email", "wechat", "phone", "ding_talk") 50 | if err != nil { 51 | logs.Error(err) 52 | } 53 | mail.Level = template2.AlertSeverityTo(mail.Level) 54 | mail.Status = template2.AlertType(mail.Status) 55 | for _, v := range plist { 56 | SendEmailAlert(mail, v) 57 | } 58 | } 59 | 60 | func PopAllMail() []*Event { 61 | ret := []*Event{} 62 | for { 63 | var ctx = context.Background() 64 | reply, err := RDB.RPop(ctx, "mail").Result() 65 | if err != nil { 66 | if err != redis.Nil { 67 | logs.Error(err) 68 | } 69 | break 70 | } 71 | if reply == "" || reply == "nil" { 72 | continue 73 | } 74 | 75 | var mail Event 76 | err = json.Unmarshal([]byte(reply), &mail) 77 | if err != nil { 78 | logs.Error(err, reply) 79 | continue 80 | } 81 | ret = append(ret, &mail) 82 | } 83 | return ret 84 | } 85 | 86 | func SendEmailAlert(event *Event, user Manager) error { 87 | //发邮件 88 | var err error 89 | var tplname string 90 | if event.Status == "0" { 91 | tplname = "./template/mail_recovery.tpl" 92 | } else { 93 | tplname = "./template/mail_problem.tpl" 94 | } 95 | tmpl, err := template.ParseFiles("./" + tplname) 96 | if err != nil { 97 | logs.Error(err) 98 | return err 99 | } 100 | var body bytes.Buffer 101 | err = tmpl.Execute(&body, event) //将str的值合成到tmpl模版的{{.}}中,并将合成得到的文本输入到os.Stdout,返回hello, world 102 | if err != nil { 103 | logs.Error(err) 104 | return err 105 | } 106 | //tos := strings.Split(m.Emails, ",") 107 | from := beego.AppConfig.String("email_from") 108 | nickname := beego.AppConfig.String("email_nickname") 109 | secret := beego.AppConfig.String("email_secret") 110 | host := beego.AppConfig.String("email_host") 111 | port, _ := beego.AppConfig.Int("email_port") 112 | isSSL, _ := beego.AppConfig.Bool("email_isSSl") 113 | auth := smtp.PlainAuth("", from, secret, host) 114 | at := smtp.CRAMMD5Auth(from, secret) 115 | e := email.NewEmail() 116 | if nickname != "" { 117 | e.From = fmt.Sprintf("%s <%s>", nickname, from) 118 | } else { 119 | e.From = from 120 | } 121 | e.To = []string{user.Email} 122 | e.Subject = "[" + event.Status + "]" + "[" + event.Message + "]" + event.Hostname + "(" + event.HostsIP + ")" 123 | e.HTML = body.Bytes() 124 | hostAddr := fmt.Sprintf("%s:%d", host, port) 125 | if isSSL { 126 | err = e.SendWithTLS(hostAddr, auth, &tls.Config{ServerName: host}) 127 | } else { 128 | err = e.Send(hostAddr, at) 129 | } 130 | var elog EventLog 131 | if err != nil { 132 | elog = EventLog{AlarmID: int64(event.ID), EventID: event.EventID, 133 | Rule: event.Rule, Channel: "mail", User: user.Username, Account: user.Email, 134 | NotifyTime: time.Now(), NotifyContent: body.String(), 135 | Status: strconv.Itoa(EventFailed), NotifyError: err.Error(), 136 | } 137 | } else { 138 | elog = EventLog{AlarmID: int64(event.ID), EventID: event.EventID, 139 | Rule: event.Rule, Channel: "mail", User: user.Username, Account: user.Email, 140 | NotifyTime: time.Now(), NotifyContent: body.String(), 141 | Status: strconv.Itoa(EventSuccess), NotifyError: "", 142 | } 143 | } 144 | //add event log 145 | _, err = AddEventLog(&elog) 146 | if err != nil { 147 | logs.Error(err) 148 | } 149 | return nil 150 | } 151 | -------------------------------------------------------------------------------- /models/cron_wechat.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "html/template" 7 | "strconv" 8 | "strings" 9 | "time" 10 | template2 "zbxtable/utils" 11 | 12 | "github.com/astaxie/beego/logs" 13 | "github.com/astaxie/beego/orm" 14 | "github.com/xen0n/go-workwx" 15 | ) 16 | 17 | // copy from open-facon-plus 18 | func ConsumeWechat() { 19 | for { 20 | L := PopAllWechat() 21 | if len(L) == 0 { 22 | time.Sleep(time.Millisecond * 200) 23 | continue 24 | } 25 | SendWechatList(L) 26 | } 27 | } 28 | func SendWechatList(L []*Event) { 29 | for _, v := range L { 30 | WechatWorkerChan <- 1 31 | go SendWechat(v) 32 | } 33 | } 34 | 35 | func SendWechat(event *Event) { 36 | defer func() { 37 | <-WechatWorkerChan 38 | }() 39 | o := orm.NewOrm() 40 | ids := strings.Split(event.ToUsers, ",") 41 | var user Manager 42 | var plist []Manager 43 | _, err := o.QueryTable(user).Filter("id__in", ids). 44 | All(&plist, "id", "username", "email", "wechat", "phone", "ding_talk") 45 | if err != nil { 46 | logs.Error(err) 47 | } 48 | var tplname string 49 | if event.Status == "0" { 50 | tplname = "./template/wechat_recovery.tpl" 51 | } else { 52 | tplname = "./template/wechat_problem.tpl" 53 | } 54 | event.Level = template2.AlertSeverityTo(event.Level) 55 | event.Status = template2.AlertType(event.Status) 56 | tmpl, err := template.ParseFiles("./" + tplname) 57 | if err != nil { 58 | logs.Error(err) 59 | return 60 | } 61 | var body bytes.Buffer 62 | err = tmpl.Execute(&body, event) 63 | if err != nil { 64 | logs.Error(err) 65 | return 66 | } 67 | for _, v := range plist { 68 | SendWechatAlert(v, event, body.String()) 69 | } 70 | } 71 | func SendWechatAlert(user Manager, event *Event, content string) error { 72 | tos := workwx.Recipient{ 73 | UserIDs: []string{user.Wechat}, 74 | } 75 | err := WeApp.SendTextMessage(&tos, content, false) 76 | var elog EventLog 77 | 78 | if err != nil { 79 | elog = EventLog{AlarmID: int64(event.ID), EventID: event.EventID, 80 | Rule: event.Rule, Channel: "wechat", User: user.Username, Account: user.Wechat, 81 | NotifyTime: time.Now(), NotifyContent: content, 82 | Status: strconv.Itoa(EventFailed), NotifyError: err.Error(), 83 | } 84 | 85 | } else { 86 | elog = EventLog{AlarmID: int64(event.ID), EventID: event.EventID, 87 | Rule: event.Rule, Channel: "wechat", User: user.Username, Account: user.Wechat, 88 | NotifyTime: time.Now(), NotifyContent: content, 89 | Status: strconv.Itoa(EventSuccess), NotifyError: "", 90 | } 91 | } 92 | //add event log 93 | _, err = AddEventLog(&elog) 94 | if err != nil { 95 | logs.Error(err) 96 | } 97 | //update alalrm status 98 | return nil 99 | } 100 | 101 | func PopAllWechat() []*Event { 102 | ret := []*Event{} 103 | for { 104 | var ctx = context.Background() 105 | reply, err := RDB.RPop(ctx, "wechat").Result() 106 | if err != nil { 107 | break 108 | } 109 | if reply == "" || reply == "nil" { 110 | continue 111 | } 112 | 113 | var mail Event 114 | err = json.Unmarshal([]byte(reply), &mail) 115 | if err != nil { 116 | logs.Error(err, reply) 117 | continue 118 | } 119 | ret = append(ret, &mail) 120 | } 121 | return ret 122 | } 123 | -------------------------------------------------------------------------------- /models/egress.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/orm" 5 | "time" 6 | ) 7 | 8 | //TableName alarm 9 | func (t *Egress) TableName() string { 10 | return TableName("egress") 11 | } 12 | 13 | type Egress struct { 14 | ID int64 `orm:"column(id);auto" json:"id"` 15 | NameOne string `orm:"column(name_one);size(255)" json:"name_one"` 16 | InOne string `orm:"column(in_one);size(255)" json:"in_one"` 17 | OutOne string `orm:"column(out_one);size(255)" json:"out_one"` 18 | NameTwo string `orm:"column(name_two);size(255)" json:"name_two"` 19 | InTwo string `orm:"column(in_two);size(255)" json:"in_two"` 20 | OutTwo string `orm:"column(out_two);size(255)" json:"out_two"` 21 | CreatedAt time.Time `orm:"column(created_at);type(datetime);auto_now_add" json:"created_at"` 22 | Status int `orm:"column(status);size(200)" json:"status"` 23 | } 24 | 25 | //get id 26 | func GetEgress() (v *Egress, err error) { 27 | o := orm.NewOrm() 28 | v = &Egress{ID: 1} 29 | if err = o.Read(v); err == nil { 30 | return v, nil 31 | } 32 | return nil, err 33 | } 34 | 35 | //get all 36 | func UpdateEgress(m *Egress) (err error) { 37 | o := orm.NewOrm() 38 | v := Egress{ID: m.ID} 39 | err = o.Read(&v) 40 | if err != nil { 41 | return err 42 | } 43 | v.NameOne = m.NameOne 44 | v.InOne = m.InOne 45 | v.OutOne = m.OutOne 46 | v.NameTwo = m.NameTwo 47 | v.InTwo = m.InTwo 48 | v.OutTwo = m.OutTwo 49 | m.CreatedAt = v.CreatedAt 50 | v.Status = 1 51 | _, err = o.Update(m, "NameOne", "InOne", "OutOne", 52 | "NameTwo", "InTwo", "OutTwo", 53 | "CreatedAt", "Status") 54 | if err != nil { 55 | return err 56 | } 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /models/event.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/orm" 5 | "time" 6 | ) 7 | 8 | const ( 9 | EventSuccess = iota // 0 10 | EventFailed // 1 11 | //Notify // 2 12 | ) 13 | 14 | //AlarmList struct 15 | type EventLogRes struct { 16 | Code int `json:"code"` 17 | Message string `json:"message"` 18 | Data struct { 19 | Items []EventLog `json:"items"` 20 | Total int64 `json:"total"` 21 | } `json:"data"` 22 | } 23 | 24 | type EventLog struct { 25 | ID int `orm:"column(id);auto" json:"id"` 26 | AlarmID int64 `orm:"column(alarm_id);size(100);null" json:"alarm_id"` 27 | EventID int64 `orm:"column(event_id);size(100);null" json:"eventid"` 28 | Rule string `orm:"column(rule);size(100);null" json:"rule"` 29 | Channel string `orm:"column(channel);size(100);null" json:"channel"` 30 | User string `orm:"column(user);size(100);null" json:"user"` 31 | Account string `orm:"column(account);size(100);null" json:"account"` 32 | NotifyTime time.Time `orm:"column(notify_time);type(datetime);null" json:"notify_time"` 33 | NotifyContent string `orm:"column(notify_content);type(text);null" json:"notify_content"` 34 | NotifyError string `orm:"column(notify_error);type(text);null" json:"notify_error"` 35 | Status string `orm:"column(status);size(10);null" json:"status"` 36 | } 37 | 38 | //TableName alarm 39 | func (t *EventLog) TableName() string { 40 | return TableName("event_log") 41 | } 42 | 43 | type EventTpl struct { 44 | HostsID string `json:"host_id"` 45 | HostHost string `json:"host_host"` 46 | Hostname string `json:"hostname"` 47 | HostsIP string `json:"host_ip"` 48 | HostGroup string `json:"host_group"` 49 | EventTime string `json:"event_time"` 50 | Severity string `json:"severity"` 51 | TriggerID int64 `json:"trigger_id"` 52 | TriggerName string `json:"trigger_name"` 53 | TriggerKey string `json:"trigger_key"` 54 | TriggerValue string `json:"trigger_value"` 55 | ItemID int64 `json:"item_id"` 56 | ItemName string `json:"item_name"` 57 | ItemValue string `json:"item_value"` 58 | EventID int64 `json:"event_id"` 59 | EventDuration string `json:"event_duration"` 60 | } 61 | 62 | type Event struct { 63 | ID int `orm:"column(id);auto" json:"id"` 64 | TenantID string `orm:"column(tenant_id);size(255)" json:"tenant_id"` 65 | HostID string `orm:"column(host_id);size(255)" json:"host_id"` 66 | Hostname string `orm:"column(hostname);size(255)" json:"hostname"` 67 | Host string `orm:"column(host);size(200)" json:"host"` 68 | HostsIP string `orm:"column(host_ip);size(200)" json:"host_ip"` 69 | TriggerID int64 `orm:"column(trigger_id);size(200)" json:"trigger_id"` 70 | ItemID int64 `orm:"column(item_id);size(200)" json:"item_id"` 71 | ItemName string `orm:"column(item_name);size(3000)" json:"item_name"` 72 | ItemValue string `orm:"column(item_value);size(3000)" json:"item_value"` 73 | Hgroup string `orm:"column(hgroup);size(200)" json:"hgroup"` 74 | OccurTime time.Time `orm:"column(occur_time);type(datetime)" json:"occur_time"` 75 | Level string `orm:"column(level);size(200)" json:"level"` 76 | Message string `orm:"column(message);size(3000)" json:"message"` 77 | Hkey string `orm:"column(hkey);size(3000)" json:"hkey"` 78 | Detail string `orm:"column(detail);size(3000)" json:"detail"` 79 | Status string `orm:"column(status);size(200)" json:"status"` 80 | EventID int64 `orm:"column(event_id);size(200)" json:"eventid"` 81 | EventDuration string `orm:"column(event_duration);size(50)" json:"event_duration"` 82 | Rule string `orm:"column(rule);size(200)" json:"rule"` 83 | RuleType string `orm:"column(rule_type);size(10)" json:"rule_type"` 84 | Channel string `orm:"column(channel);size(255)" json:"channel"` 85 | ToUsers string `orm:"column(to_users);size(255)" json:"to_users"` 86 | UserIds string `orm:"column(user_ids);size(255)" json:"user_ids"` 87 | GroupIds string `orm:"column(group_ids);size(255)" json:"group_ids"` 88 | } 89 | 90 | // AddAlarm insert a new Alarm into database and returns 91 | // last inserted Id on success. 92 | func AddEventLog(m *EventLog) (id int64, err error) { 93 | o := orm.NewOrm() 94 | id, err = o.Insert(m) 95 | if err != nil { 96 | return 0, err 97 | } 98 | return id, nil 99 | } 100 | 101 | // GetAlarmByID retrieves Alarm by Id. Returns error if 102 | // Id doesn't exist 103 | func GetEventLogByAlarmID(id int) (v []EventLog, err error) { 104 | o := orm.NewOrm() 105 | var eventLog EventLog 106 | var thisEvents []EventLog 107 | _, err = o.QueryTable(eventLog).Filter("alarm_id", id). 108 | //OrderBy("-occurtime"). 109 | All(&thisEvents) 110 | if err != nil { 111 | return []EventLog{}, err 112 | } 113 | return thisEvents, nil 114 | } 115 | -------------------------------------------------------------------------------- /models/export_table_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // ListQuery struct 4 | type ListQuery struct { 5 | HostID string `json:"hostid"` 6 | ItemType string `json:"itemtype"` 7 | Period []string `json:"period"` 8 | } 9 | 10 | // ListQueryNew struct 11 | type ListQueryNew struct { 12 | HostID string `json:"hostid"` 13 | Item Item `json:"item"` 14 | Period []string `json:"period"` 15 | } 16 | 17 | // ListQueryAll struct 18 | type ListQueryAll struct { 19 | Host Host `json:"host"` 20 | Item Item `json:"item"` 21 | Period []string `json:"period"` 22 | } 23 | 24 | type ExportHosts struct { 25 | Hosttype string `json:"hosttype"` 26 | Hosts string `json:"hosts"` 27 | Model string `json:"model"` 28 | Ip string `json:"ip"` 29 | Available string `json:"available"` 30 | } 31 | 32 | type ExportInventory struct { 33 | HostType string `json:"hostType"` 34 | } 35 | 36 | // Itm struct 37 | type Itm struct { 38 | Itemids string `json:"itemids"` 39 | ItemName string `json:"itemname"` 40 | ItemKey string `json:"itemkey"` 41 | Status string `json:"status"` 42 | State string `json:"state"` 43 | } 44 | 45 | // ExpList struct 46 | type ExpList struct { 47 | Code int `json:"code"` 48 | Message string `json:"message"` 49 | Data struct { 50 | Items []FileSystemDataALL `json:"items"` 51 | MountPoint []string `json:"mountpoint"` 52 | FileName string `json:"filename"` 53 | } `json:"data"` 54 | } 55 | 56 | // FileSystemInfo data 57 | type FileSystemInfo struct { 58 | MountPoint string `json:"mountpoint"` 59 | ItemID string `json:"itemid"` 60 | ItemName string `json:"itemname"` 61 | ItemKey string `json:"itemkey"` 62 | } 63 | 64 | // FileSystemDataVue struct 65 | type FileSystemDataVue struct { 66 | FileSystemDataADD []FileSystemData `json:"filesystemdata"` 67 | } 68 | 69 | // FileSystemDataALL struct 70 | type FileSystemDataALL struct { 71 | MountPoint string `json:"mountpoint"` 72 | FileSystemDataADD []FileSystemData `json:"filesystemdata"` 73 | } 74 | 75 | // FileSystemData data 76 | type FileSystemData struct { 77 | MountPoint string `json:"mountpoint"` 78 | ItemID string `json:"itemid"` 79 | ItemName string `json:"itemname"` 80 | ItemKey string `json:"itemkey"` 81 | Clock string `json:"clock"` 82 | Num string `json:"num"` 83 | ValueMin string `json:"value_min"` 84 | ValueAvg string `json:"value_avg"` 85 | ValueMax string `json:"value_max"` 86 | } 87 | 88 | // Insp a 89 | type Insp struct { 90 | HostName string `json:"hostname"` 91 | CPULoad float64 `json:"cpuload"` 92 | MemPct float64 `json:"mempct"` 93 | } 94 | 95 | // HostsData strunct 96 | type HostsData struct { 97 | Hostid string `json:"hostid"` 98 | Host string `json:"host"` 99 | Items []struct { 100 | History string `json:"history"` 101 | Itemid string `json:"itemid"` 102 | Key string `json:"key_"` 103 | Name string `json:"name"` 104 | State string `json:"state"` 105 | Status string `json:"status"` 106 | Trends string `json:"trends"` 107 | } `json:"items"` 108 | ParentTemplates []struct { 109 | Name string `json:"name"` 110 | Templateid string `json:"templateid"` 111 | } `json:"parentTemplates"` 112 | } 113 | -------------------------------------------------------------------------------- /models/graph.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | //GetGraphByHostID by id 8 | func GetGraphByHostID(hostid int, start, end int64) ([]GraphInfo, int64, error) { 9 | rep, err := API.CallWithError("graph.get", Params{"output": "extend", 10 | "hostids": hostid, "sortfiled": "name"}) 11 | if err != nil { 12 | return []GraphInfo{}, 0, err 13 | } 14 | hba, err := json.Marshal(rep.Result) 15 | if err != nil { 16 | return []GraphInfo{}, 0, err 17 | } 18 | EndTime := time.Unix(end, 0).Format("2006-01-02 15:04:05") 19 | StartTime := time.Unix(start, 0).Format("2006-01-02 15:04:05") 20 | var hb []GraphInfo 21 | err = json.Unmarshal(hba, &hb) 22 | if err != nil { 23 | return []GraphInfo{}, 0, err 24 | } 25 | var bb GraphInfo 26 | var cc []GraphInfo 27 | for _, v := range hb { 28 | bb.GraphID = "/v1/images/" + v.GraphID + "?from=" + StartTime + "?to=" + EndTime 29 | bb.Name = v.Name 30 | cc = append(cc, bb) 31 | } 32 | return cc, int64(len(hb)), err 33 | } 34 | -------------------------------------------------------------------------------- /models/graph_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type GraphList struct { 4 | Code int `json:"code"` 5 | Message string `json:"message"` 6 | Data struct { 7 | Items []GraphInfo `json:"items"` 8 | Total int64 `json:"total"` 9 | } `json:"data"` 10 | } 11 | 12 | //GraphListQuery struct 13 | type GraphListQuery struct { 14 | Hostid string `json:"hostid"` 15 | Period []string `json:"period"` 16 | } 17 | 18 | //GraphExpQuery struc 19 | type GraphExpQuery struct { 20 | Hostids []string `json:"hostids"` 21 | Period []string `json:"period"` 22 | } 23 | 24 | //GraphInfo struct 25 | type GraphInfo struct { 26 | GraphID string `json:"graphid"` 27 | Name string `json:"name"` 28 | } 29 | 30 | //GraphIDList as 31 | type GraphIDList struct { 32 | Hosts string `json:"hosts"` 33 | GraphList []GraphInfo `json:"graphid"` 34 | } 35 | 36 | //GIDList struct 37 | type GIDList struct { 38 | GIDList []GraphIDList `json:"gidlist"` 39 | } 40 | 41 | //GraphByteInfo struct 42 | type GraphByteInfo struct { 43 | GraphID string `json:"graphid"` 44 | GraphByte []byte `json:"graphbyte"` 45 | Name string `json:"name"` 46 | } 47 | -------------------------------------------------------------------------------- /models/group.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "github.com/astaxie/beego/orm" 6 | "strconv" 7 | "strings" 8 | "time" 9 | ) 10 | 11 | type UserGroup struct { 12 | ID int `orm:"column(id);auto" json:"id"` 13 | Name string `orm:"column(name);size(255)" json:"name"` 14 | Member string `orm:"column(member);size(1000)" json:"member"` 15 | Note string `orm:"column(note);size(255)" json:"note"` 16 | Created time.Time `orm:"column(created);type(datetime);auto_now_add" json:"created"` 17 | Updated time.Time `orm:"column(updated);type(datetime);auto_now" json:"updated_at"` 18 | } 19 | 20 | //ManagerInfo struct 21 | type GroupResp struct { 22 | Code int `json:"code"` 23 | Message string `json:"message"` 24 | Data struct { 25 | Items interface{} `json:"items"` 26 | Total int64 `json:"total"` 27 | } `json:"data"` 28 | } 29 | 30 | //TableName string 31 | func (t *UserGroup) TableName() string { 32 | return TableName("user_group") 33 | } 34 | 35 | // AddManager insert a new Manager into database and returns 36 | // last inserted Id on success. 37 | func AddUserGroup(m *UserGroup) (id int64, err error) { 38 | o := orm.NewOrm() 39 | //用户是否已存在 40 | p := UserGroup{Name: m.Name} 41 | err = o.Read(&p, "name") 42 | if err == nil { 43 | return 0, errors.New("用户组存在") 44 | } 45 | //插入 46 | _, err = o.Insert(m) 47 | if err != nil { 48 | return 0, err 49 | } 50 | return 51 | } 52 | 53 | // GetAllAlarm retrieves all Alarm matches certain condition. Returns empty list if 54 | // no records exist 55 | func GetGroup(page, limit, tuser, name string) (cnt int64, userlist []UserGroup, err error) { 56 | o := orm.NewOrm() 57 | var groups []UserGroup 58 | var CountGroups []UserGroup 59 | al := new(UserGroup) 60 | pages, _ := strconv.Atoi(page) 61 | limits, _ := strconv.Atoi(limit) 62 | //count alarms 63 | cond := orm.NewCondition() 64 | if name != "" { 65 | cond = cond.And("name__icontains", name) 66 | } 67 | //管理员角色 68 | p := Manager{Username: tuser} 69 | err = o.Read(&p, "username") 70 | if err != nil { 71 | return 0, []UserGroup{}, err 72 | } 73 | if p.Role != "admin" { 74 | return 0, []UserGroup{}, err 75 | } 76 | _, err = o.QueryTable(al).SetCond(cond). 77 | All(&CountGroups) 78 | _, err = o.QueryTable(al). 79 | Limit(limits, (pages-1)*limits).SetCond(cond). 80 | All(&groups, "id", "name", "member", "note", "created", "updated") 81 | if err != nil { 82 | return 0, []UserGroup{}, err 83 | } 84 | cnt = int64(len(CountGroups)) 85 | return cnt, groups, nil 86 | } 87 | 88 | //udpate user 89 | func UpdateUserGroup(m *UserGroup, tuser string) error { 90 | o := orm.NewOrm() 91 | //role检查 92 | p := Manager{Username: tuser} 93 | err := o.Read(&p, "username") 94 | if err != nil { 95 | return err 96 | } 97 | if p.Role != "admin" { 98 | return errors.New("no permission") 99 | } 100 | // 101 | v := UserGroup{ID: m.ID} 102 | err = o.Read(&v) 103 | if err != nil { 104 | return err 105 | } 106 | //更新其他字段 107 | v.Name = m.Name 108 | v.Note = m.Note 109 | _, err = o.Update(m, "name", "note") 110 | if err != nil { 111 | return err 112 | } 113 | return nil 114 | } 115 | 116 | //UpdateGroupMember user 117 | func UpdateGroupMember(m *UserGroup, tuser string) error { 118 | o := orm.NewOrm() 119 | //role检查 120 | p := Manager{Username: tuser} 121 | err := o.Read(&p, "username") 122 | if err != nil { 123 | return err 124 | } 125 | if p.Role != "admin" { 126 | return errors.New("no permission") 127 | } 128 | // 129 | v := UserGroup{ID: m.ID} 130 | err = o.Read(&v) 131 | if err != nil { 132 | return err 133 | } 134 | //更新字段 135 | new1 := strings.Replace(m.Member, "[", "", -1) 136 | new2 := strings.Replace(new1, "]", "", -1) 137 | new3 := strings.TrimSuffix(strings.Replace(new2, `"`, ``, -1), `,`) 138 | m.Member = new3 139 | v.Member = m.Member 140 | _, err = o.Update(m, "member") 141 | if err != nil { 142 | return err 143 | } 144 | return nil 145 | } 146 | 147 | func DeleteGroup(id int, tuser string) (err error) { 148 | o := orm.NewOrm() 149 | //role检查 150 | p := Manager{Username: tuser} 151 | err = o.Read(&p, "username") 152 | if err != nil { 153 | return err 154 | } 155 | //not admin role return err 156 | if p.Role != "admin" { 157 | return errors.New("no permission") 158 | } 159 | v := UserGroup{ID: id} 160 | //admin not delete 161 | //if id == 1 { 162 | // return errors.New("admin user cannot delete ") 163 | //} 164 | // ascertain id exists in the database 165 | if err = o.Read(&v); err == nil { 166 | //if v.Username == tuser { 167 | // return errors.New("cannot delete myself") 168 | //} 169 | _, err = o.Delete(&UserGroup{ID: id}) 170 | if err != nil { 171 | return err 172 | } 173 | return nil 174 | } 175 | return nil 176 | } 177 | -------------------------------------------------------------------------------- /models/history_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // HistoryList struct 4 | type HistoryList struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items []History `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | // History struct 14 | type History struct { 15 | Itemid string `json:"itemid"` 16 | Clock string `json:"clock"` 17 | Value string `json:"value"` 18 | Ns string `json:"ns"` 19 | } 20 | 21 | // ListQueryAll struct 22 | type HistoryQuery struct { 23 | Itemids string `json:"itemids"` 24 | History string `json:"history"` 25 | Period []string `json:"period"` 26 | } 27 | 28 | // XAxis x轴 29 | type XAxis struct { 30 | Type string `json:"type"` 31 | Data []string `json:"data"` 32 | } 33 | 34 | // YAxis y轴 35 | type YAxis struct { 36 | Name string `json:"name"` 37 | Data []float64 `json:"data"` 38 | Type string `json:"type"` 39 | ItemStyle ItemStyle `json:"itemStyle"` 40 | } 41 | type ItemStyle struct { 42 | Opacity float64 `json:"opacity"` 43 | Color string `json:"color"` 44 | } 45 | 46 | // Legend 图例 47 | type Legend struct { 48 | Data []string `json:"data"` 49 | } 50 | 51 | // TrafficSeries 流量图数据 52 | type TrafficSeries struct { 53 | XAxis XAxis `json:"xAxis"` 54 | YAxis []YAxis `json:"yAxis"` 55 | Legend Legend `json:"legend"` 56 | TrafficTable []TrafficTable `json:"table"` 57 | } 58 | 59 | // TrafficeTable 流量表数据 60 | type TrafficTable struct { 61 | Name string `json:"name"` 62 | Min string `json:"min"` 63 | Max string `json:"max"` 64 | Avg string `json:"avg"` 65 | Th95PercAvg string `json:"th_perc_avg"` 66 | Th95PercVal string `json:"th_perc_val"` 67 | } 68 | 69 | // ErrorsSeries 错误包图数据 70 | type ErrorsSeries struct { 71 | XAxis XAxis `json:"xAxis"` 72 | YAxis []YAxis `json:"yAxis"` 73 | Legend Legend `json:"legend"` 74 | Table []Table `json:"table"` 75 | } 76 | 77 | // DiscardedSeries 丢弃包图数据 78 | type DiscardedSeries struct { 79 | XAxis XAxis `json:"xAxis"` 80 | YAxis []YAxis `json:"yAxis"` 81 | Legend Legend `json:"legend"` 82 | Table []Table `json:"table"` 83 | } 84 | 85 | // OperationalStatusSeries 运行状态图数据 86 | type OperationalStatusSeries struct { 87 | XAxis XAxis `json:"xAxis"` 88 | YAxis []YAxis `json:"yAxis"` 89 | Legend Legend `json:"legend"` 90 | Table []Table `json:"table"` 91 | } 92 | type Table struct { 93 | Name string `json:"name"` 94 | Min string `json:"min"` 95 | Max string `json:"max"` 96 | Avg string `json:"avg"` 97 | } 98 | 99 | type TrafficData struct { 100 | TrafficSeries TrafficSeries `json:"traffic_series"` 101 | ErrorsSeries ErrorsSeries `json:"errors_series"` 102 | DiscardedSeries DiscardedSeries `json:"discarded_series"` 103 | OperationalSeries OperationalStatusSeries `json:"operational_status_series"` 104 | } 105 | -------------------------------------------------------------------------------- /models/host_group.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "log" 5 | "math" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | //GetAllHostGroups func 11 | func GetAllHostGroups(page, limit, groups string) ([]HostGroups, int64, error) { 12 | rep, err := API.Call("hostgroup.get", Params{"output": "extend", 13 | "selectHosts": "count"}) 14 | if err != nil { 15 | return []HostGroups{}, 0, err 16 | } 17 | hba, err := json.Marshal(rep.Result) 18 | if err != nil { 19 | return []HostGroups{}, 0, err 20 | } 21 | var hb []HostGroups 22 | err = json.Unmarshal(hba, &hb) 23 | if err != nil { 24 | return []HostGroups{}, 0, err 25 | } 26 | var dt []HostGroups 27 | var d HostGroups 28 | if groups != "" { 29 | for _, v := range hb { 30 | if strings.Contains(v.Name, groups) { 31 | d.GroupID = v.GroupID 32 | d.Name = v.Name 33 | d.Hosts = v.Hosts 34 | d.Internal = v.Internal 35 | dt = append(dt, d) 36 | } 37 | } 38 | } else { 39 | for _, v := range hb { 40 | if strings.Contains(v.Name, groups) { 41 | d.GroupID = v.GroupID 42 | d.Name = v.Name 43 | d.Hosts = v.Hosts 44 | d.Internal = v.Internal 45 | dt = append(dt, d) 46 | } 47 | } 48 | } 49 | //页数 50 | IntPage, err := strconv.Atoi(page) 51 | if err != nil { 52 | IntPage = 1 53 | } 54 | //每页数量 55 | IntLimit, err := strconv.Atoi(limit) 56 | if err != nil { 57 | IntLimit = 10 58 | } 59 | // //fmt.Println(hb.Host) 60 | //如果dt为空直接返回 61 | if len(dt) == 0 { 62 | return dt, int64(len(dt)), err 63 | } 64 | //分页 65 | nums := len(dt) 66 | 67 | //page总数 68 | totalpages := int(math.Ceil(float64(nums) / float64(IntLimit))) 69 | if IntPage >= totalpages { 70 | IntPage = totalpages 71 | } 72 | if IntPage <= 0 { 73 | IntPage = 1 74 | } 75 | //结束页数据 76 | var end int 77 | //begin 开始页数据 78 | 79 | begin := (IntPage - 1) * IntLimit 80 | if IntPage == totalpages { 81 | end = nums 82 | } 83 | if IntPage < totalpages { 84 | end = IntPage * IntLimit 85 | } else { 86 | end = nums 87 | } 88 | var newgroups []HostGroups 89 | for i := begin; i < end; i++ { 90 | newgroups = append(newgroups, dt[i]) 91 | } 92 | return newgroups, int64(len(dt)), err 93 | } 94 | 95 | //GetAllHostGroupsList func 96 | func GetAllHostGroupsList() ([]HostTree, int64, error) { 97 | selectHosts := []string{"hostid", "name", "status"} 98 | rep, err := API.Call("hostgroup.get", Params{"output": "extend", 99 | "selectHosts": selectHosts}) 100 | if err != nil { 101 | return []HostTree{}, 0, err 102 | } 103 | hba, err := json.Marshal(rep.Result) 104 | if err != nil { 105 | return []HostTree{}, 0, err 106 | } 107 | var hb []HostTree 108 | 109 | err = json.Unmarshal(hba, &hb) 110 | if err != nil { 111 | log.Println(err) 112 | return []HostTree{}, 0, err 113 | } 114 | return hb, int64(len(hb)), err 115 | } 116 | 117 | //GetAllHostGroupsList func 118 | func GetAllGroupsList() ([]HostTree, int64, error) { 119 | rep, err := API.Call("hostgroup.get", Params{"output": "extend"}) 120 | if err != nil { 121 | return []HostTree{}, 0, err 122 | } 123 | hba, err := json.Marshal(rep.Result) 124 | if err != nil { 125 | return []HostTree{}, 0, err 126 | } 127 | var hb []HostTree 128 | 129 | err = json.Unmarshal(hba, &hb) 130 | if err != nil { 131 | log.Println(err) 132 | return []HostTree{}, 0, err 133 | } 134 | return hb, int64(len(hb)), err 135 | } 136 | 137 | //GetHostsInfoByGroupID func 138 | func GetHostsInfoByGroupID(GroupID string) ([]HostGroupBYGroupID, error) { 139 | output := []string{"groupid", "name"} 140 | selectHosts := []string{"hostid", "name", "status"} 141 | selectInterfaces := []string{"main", "port"} 142 | rep, err := API.Call("hostgroup.get", Params{"output": output, 143 | "groupids": GroupID, "selectHosts": selectHosts, 144 | "selectInterfaces": selectInterfaces}) 145 | 146 | if err != nil { 147 | log.Fatalln(err) 148 | return []HostGroupBYGroupID{}, err 149 | } 150 | hba, err := json.Marshal(rep.Result) 151 | if err != nil { 152 | log.Fatalln(err) 153 | return []HostGroupBYGroupID{}, err 154 | } 155 | var hb []HostGroupBYGroupID 156 | err = json.Unmarshal(hba, &hb) 157 | if err != nil { 158 | log.Fatalln(err) 159 | return []HostGroupBYGroupID{}, err 160 | } 161 | return hb, err 162 | } 163 | 164 | //GetHostsByGroupID func 165 | func GetHostsByGroupID(GroupID string) ([]HostGroupBYGroupID, error) { 166 | output := []string{"groupid", "name"} 167 | selectHosts := []string{"hostid", "name", "status"} 168 | rep, err := API.Call("hostgroup.get", Params{"output": output, 169 | "groupids": GroupID, "selectHosts": selectHosts}) 170 | 171 | if err != nil { 172 | log.Fatalln(err) 173 | return []HostGroupBYGroupID{}, err 174 | } 175 | hba, err := json.Marshal(rep.Result) 176 | if err != nil { 177 | log.Fatalln(err) 178 | return []HostGroupBYGroupID{}, err 179 | } 180 | 181 | var hb []HostGroupBYGroupID 182 | 183 | err = json.Unmarshal(hba, &hb) 184 | if err != nil { 185 | log.Fatalln(err) 186 | return []HostGroupBYGroupID{}, err 187 | } 188 | return hb, err 189 | } 190 | 191 | //GetHostsByGroupIDList func 192 | func GetHostsByGroupIDList(GroupID string) ([]Hosts, error) { 193 | output := []string{"groupid", "name"} 194 | selectHosts := []string{"hostid", "name", "status"} 195 | rep, err := API.Call("hostgroup.get", Params{"output": output, 196 | "groupids": GroupID, "selectHosts": selectHosts}) 197 | if err != nil { 198 | return []Hosts{}, err 199 | } 200 | if err != nil { 201 | return []Hosts{}, err 202 | } 203 | hba, err := json.Marshal(rep.Result) 204 | if err != nil { 205 | return []Hosts{}, err 206 | } 207 | var hb []HostGroupBYGroupID 208 | err = json.Unmarshal(hba, &hb) 209 | if err != nil { 210 | return []Hosts{}, err 211 | } 212 | var b Hosts 213 | var list []Hosts 214 | for _, v := range hb { 215 | for _, vv := range v.Hosts { 216 | b.HostID = vv.HostID 217 | b.Name = vv.Name 218 | b.Status = vv.Status 219 | list = append(list, b) 220 | } 221 | } 222 | return list, nil 223 | } 224 | -------------------------------------------------------------------------------- /models/host_group_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //HostGroupsList struct 4 | type HostGroupsList struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items []HostGroups `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | //HostGroupBYGroupIDList struct 14 | type HostGroupBYGroupIDList struct { 15 | Code int `json:"code"` 16 | Message string `json:"message"` 17 | Data struct { 18 | Items []HostGroupBYGroupID `json:"items"` 19 | Total int64 `json:"total"` 20 | } `json:"data"` 21 | } 22 | 23 | //HostGroups struct 24 | type HostGroups struct { 25 | GroupID string `json:"groupid"` 26 | Name string `json:"name"` 27 | Internal string `json:"internal"` 28 | Flags string `json:"flags"` 29 | Hosts string `json:"hosts"` 30 | } 31 | 32 | //HostGroupsPlist list 33 | type HostGroupsPlist struct { 34 | GroupID string `json:"groupid,omitempty"` 35 | Name string `json:"name,omitempty"` 36 | Internal string `json:"internal,omitempty"` 37 | Flags string `json:"flags,omitempty"` 38 | Hosts []Host `json:"hosts,omitempty"` 39 | } 40 | 41 | //HostTreeList sst 42 | type HostTreeList struct { 43 | Code int `json:"code"` 44 | Message string `json:"message"` 45 | Data struct { 46 | Items []HostTree `json:"items"` 47 | Total int64 `json:"total"` 48 | } `json:"data"` 49 | } 50 | 51 | //HostTree struct 52 | type HostTree struct { 53 | GroupID string `json:"groupid"` 54 | Name string `json:"name"` 55 | Chrildren []struct { 56 | HostID string `json:"hostid"` 57 | Name string `json:"name"` 58 | } `json:"hosts"` 59 | } 60 | type GroupHosts struct { 61 | HostID string `json:"hostid,omitempty"` 62 | Name string `json:"name,omitempty"` 63 | Status string `json:"status"` 64 | } 65 | 66 | //HostGroupBYGroupID struct 67 | type HostGroupBYGroupID struct { 68 | GroupID string `json:"groupid,omitempty"` 69 | Name string `json:"name"` 70 | Hosts []GroupHosts `json:"hosts"` 71 | } 72 | -------------------------------------------------------------------------------- /models/index.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strconv" 7 | 8 | "github.com/astaxie/beego/logs" 9 | ) 10 | 11 | func getCountByType(hostType string) (int64, error) { 12 | inventoryParams := make(map[string]string) 13 | inventoryParams["type"] = hostType 14 | hostCount, err := API.CallWithError("host.get", Params{ 15 | "output": "extend", 16 | "searchInventory": inventoryParams, 17 | "countOutput": true}) 18 | if err != nil { 19 | return 0, err 20 | } 21 | count, _ := strconv.ParseInt(hostCount.Result.(string), 10, 64) 22 | return count, nil 23 | } 24 | 25 | func GetCountHost() (IndexInfo, error) { 26 | d := IndexInfo{} 27 | var err error 28 | //d.Hosts, err = getCountByType("host.get") 29 | //d.Items, err = getCountByType("item.get") 30 | //d.Problems, err = getCountByType("problem.get") 31 | //d.Triggers, err = getCountByType("trigger.get") 32 | d.LinCount, err = getCountByType("VM_LIN") 33 | if err != nil { 34 | return d, err 35 | } 36 | d.WinCount, err = getCountByType("VM_WIN") 37 | if err != nil { 38 | return d, err 39 | } 40 | d.SRVCount, err = getCountByType("HW_SRV") 41 | if err != nil { 42 | return d, err 43 | } 44 | d.NETCount, err = getCountByType("HW_NET") 45 | if err != nil { 46 | return IndexInfo{}, err 47 | } 48 | return d, nil 49 | } 50 | 51 | // GetTopList top数据获取 52 | func GetTopList(host_type, metrics_type, top_num string) (info []TopList, err error) { 53 | var MetType1, MetType2 string 54 | switch host_type { 55 | case "VM_WIN": 56 | MetType1 = "WIN" 57 | case "VM_LIN": 58 | MetType1 = "LIN" 59 | default: 60 | MetType1 = "WIN" 61 | } 62 | switch metrics_type { 63 | case "CPU": 64 | MetType2 = "CPU" 65 | case "MEM": 66 | MetType2 = "MEM" 67 | default: 68 | MetType1 = "CPU" 69 | } 70 | var top_n int64 71 | p, err := strconv.ParseInt(top_num, 10, 64) 72 | if err != nil { 73 | logs.Error(err) 74 | top_n = 5 75 | } else { 76 | top_n = p 77 | } 78 | var ctx = context.Background() 79 | ret, err := RDB.ZRevRangeWithScores(ctx, MetType1+"_"+MetType2, 0, top_n).Result() 80 | if err != nil { 81 | return []TopList{}, err 82 | 83 | } 84 | var p1 TopList 85 | var p2 []TopList 86 | for _, z := range ret { 87 | p1.Hostname = fmt.Sprintf("%v", z.Member) 88 | p1.Score = z.Score 89 | p2 = append(p2, p1) 90 | } 91 | return p2, nil 92 | } 93 | func GetInventory() ([]Treeinventory, error) { 94 | //var list = []string{"VM_LIN", "VM_WIN", "HW_NET", "HW_SRV"} 95 | //var listmap map[string][]TreeChildren 96 | //listmap = make(map[string][]TreeChildren) 97 | //var ctx = context.Background() 98 | //for _, v := range list { 99 | // var ArrayOne []TreeChildren 100 | // p, err := RDB.Get(ctx, v+"_INVENTORY").Result() 101 | // if err != nil { 102 | // listmap[v] = ArrayOne 103 | // logs.Error(err) 104 | // continue 105 | // } 106 | // err = json.Unmarshal([]byte(p), &ArrayOne) 107 | // if err != nil { 108 | // listmap[v] = ArrayOne 109 | // logs.Error(err) 110 | // } 111 | // listmap[v] = ArrayOne 112 | //} 113 | //tree 114 | //TwoTree := []TwoChildren{ 115 | // {10, "Linux操作系统", listmap["VM_LIN"]}, 116 | // {11, "Windows操作系统", listmap["VM_WIN"]}, 117 | // {12, "网络设备", listmap["HW_NET"]}, 118 | // {13, "物理服务器", listmap["HW_SRV"]}, 119 | //} 120 | TwoTree := []TwoChildren{ 121 | {10, "Linux操作系统"}, 122 | {11, "Windows操作系统"}, 123 | {12, "网络设备"}, 124 | {13, "物理服务器"}, 125 | } 126 | tree := make([]Treeinventory, 1) 127 | tree[0].ID = 0 128 | tree[0].Name = "资产树" 129 | tree[0].TwoChildren = TwoTree 130 | 131 | return tree, nil 132 | 133 | } 134 | func GetOverviewData() (OverviewList, error) { 135 | var list = []string{"VM_LIN", "VM_WIN", "HW_NET", "HW_SRV"} 136 | //var one OverviewList 137 | //var datalist []OverviewList 138 | listmap := make(map[string][]Hosts) 139 | var ctx = context.Background() 140 | for _, v := range list { 141 | var ArrayOne []Hosts 142 | p, err := RDB.Get(ctx, v+"_OVERVIEW").Result() 143 | if err != nil { 144 | logs.Error(err) 145 | continue 146 | } 147 | err = json.Unmarshal([]byte(p), &ArrayOne) 148 | if err != nil { 149 | logs.Error(err) 150 | continue 151 | } 152 | listmap[v] = ArrayOne 153 | } 154 | var newList OverviewList 155 | newList.Lin = listmap["VM_LIN"] 156 | newList.Win = listmap["VM_WIN"] 157 | newList.NET = listmap["HW_NET"] 158 | newList.SRV = listmap["HW_SRV"] 159 | return newList, nil 160 | } 161 | func GetEgressData() (EgressList, error) { 162 | var ctx = context.Background() 163 | p, err := RDB.Get(ctx, "Egress").Result() 164 | if err != nil { 165 | logs.Error(err) 166 | return EgressList{}, err 167 | } 168 | var data EgressList 169 | err = json.Unmarshal([]byte(p), &data) 170 | if err != nil { 171 | logs.Error(err) 172 | return EgressList{}, err 173 | } 174 | return data, nil 175 | } 176 | 177 | func GetZbxSession() (string, error) { 178 | var ctx = context.Background() 179 | p, err := RDB.Get(ctx, "zbx_session").Result() 180 | if err != nil { 181 | logs.Error(err) 182 | return "", err 183 | } 184 | return p, nil 185 | } 186 | -------------------------------------------------------------------------------- /models/index_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // TrendRes resp 4 | // IndexInfo struct 5 | type IndexInfo struct { 6 | Hosts int64 `json:"hosts"` 7 | Items int64 `json:"items"` 8 | Triggers int64 `json:"triggers"` 9 | Problems int64 `json:"problems"` 10 | WinCount int64 `json:"win_count"` //Windows主机 11 | LinCount int64 `json:"lin_count"` //Linux主机 12 | NETCount int64 `json:"net_count"` //网络设备 13 | SRVCount int64 `json:"srv_count"` //硬件服务器 14 | } 15 | 16 | type RouRes struct { 17 | Code int `json:"code"` 18 | Message string `json:"message"` 19 | Data struct { 20 | Items interface{} `json:"items"` 21 | } `json:"data"` 22 | } 23 | type RouterRes struct { 24 | Router string `json:"router"` 25 | Children []MenuItem `json:"children"` 26 | } 27 | 28 | type InfoRes struct { 29 | Code int `json:"code"` 30 | Message string `json:"message"` 31 | Data struct { 32 | Items IndexInfo `json:"items"` 33 | } `json:"data"` 34 | } 35 | type VerRes struct { 36 | Code int `json:"code"` 37 | Message string `json:"message"` 38 | Data struct { 39 | Items version `json:"items"` 40 | } `json:"data"` 41 | } 42 | type version struct { 43 | ZabbixVersion string `json:"zabbixVersion"` 44 | Version string `json:"version"` 45 | GitHash string `json:"gitHash"` 46 | BuildTime string `json:"buildTime"` 47 | } 48 | 49 | type TopRes struct { 50 | Code int `json:"code"` 51 | Message string `json:"message"` 52 | Data struct { 53 | Items []TopList `json:"top_list"` 54 | } `json:"data"` 55 | } 56 | type TreeRes struct { 57 | Code int `json:"code"` 58 | Message string `json:"message"` 59 | Data struct { 60 | Items []Treeinventory `json:"items"` 61 | } `json:"data"` 62 | } 63 | type TopList struct { 64 | Hostname string `json:"hostname"` 65 | Score float64 `json:"score"` 66 | } 67 | 68 | type Treeinventory struct { 69 | ID int64 `json:"id"` 70 | Name string `json:"name"` 71 | TwoChildren []TwoChildren `json:"children"` 72 | } 73 | type TwoChildren struct { 74 | ID int64 `json:"id"` 75 | Name string `json:"name"` 76 | //TreeChildren []TreeChildren `json:"children"` 77 | } 78 | type TreeChildren struct { 79 | ID int64 `json:"id"` 80 | Name string `json:"name"` 81 | } 82 | type OverviewRes struct { 83 | Code int `json:"code"` 84 | Message string `json:"message"` 85 | Data struct { 86 | Items OverviewList `json:"items"` 87 | } `json:"data"` 88 | } 89 | type OverviewList struct { 90 | Win []Hosts `json:"vm_win"` 91 | Lin []Hosts `json:"vm_lin"` 92 | NET []Hosts `json:"hw_net"` 93 | SRV []Hosts `json:"hw_srv"` 94 | } 95 | type EgressRes struct { 96 | Code int `json:"code"` 97 | Message string `json:"message"` 98 | Data struct { 99 | Items interface{} `json:"items"` 100 | } `json:"data"` 101 | } 102 | type EgressList struct { 103 | NameOne string `json:"name_one"` 104 | InOne string `json:"in_one"` 105 | OutOne string `json:"out_one"` 106 | NameTwo string `json:"name_two"` 107 | InTwo string `json:"in_two"` 108 | OutTwo string `json:"out_two"` 109 | Date string `json:"date"` 110 | } 111 | 112 | type SessionRes struct { 113 | Code int `json:"code"` 114 | Message string `json:"message"` 115 | Data struct { 116 | Items string `json:"items"` 117 | } `json:"data"` 118 | } 119 | -------------------------------------------------------------------------------- /models/inspect.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "bytes" 5 | "strconv" 6 | "time" 7 | 8 | "github.com/360EntSecGroup-Skylar/excelize" 9 | ) 10 | 11 | //ExpInspect 按组巡检报告导出 12 | func ExpInspect(groupname string, Insp []Insp) ([]byte, error) { 13 | 14 | f := excelize.NewFile() 15 | // Create a new sheet. 16 | index := f.NewSheet("Sheet1") 17 | stylecenter, err := f.NewStyle(`{"alignment":{"horizontal":"center","vertical":"center","wrap_text":true}}`) 18 | if err != nil { 19 | return []byte{}, nil 20 | } 21 | 22 | style1111, err := f.NewStyle(`{"font":{"bold":true,"size":36,"color":"#777777"}, 23 | "alignment":{"horizontal":"center","vertical":"center"}}`) 24 | if err != nil { 25 | return []byte{}, nil 26 | } 27 | f.MergeCell("Sheet1", "A1", "H1") 28 | f.SetCellStyle("Sheet1", "A1", "H1", style1111) 29 | f.SetCellValue("Sheet1", "A1", "服务器设备日常巡检") 30 | //标题 31 | f.SetColWidth("Sheet1", "A", "A", 4) 32 | f.MergeCell("Sheet1", "A2", "A3") 33 | f.SetCellStyle("Sheet1", "G2", "G3", stylecenter) 34 | f.MergeCell("Sheet1", "B2", "B3") 35 | f.SetCellStyle("Sheet1", "B2", "B3", stylecenter) 36 | f.SetCellValue("Sheet1", "B2", "设备型号") 37 | f.MergeCell("Sheet1", "C2", "E2") 38 | f.SetCellStyle("Sheet1", "C2", "E2", stylecenter) 39 | f.SetCellStyle("Sheet1", "C3", "E3", stylecenter) 40 | f.SetColWidth("Sheet1", "C", "E", 12) 41 | f.SetCellValue("Sheet1", "C2", "运行状态检查") 42 | f.SetCellValue("Sheet1", "C3", "CPU利用率") 43 | f.SetCellValue("Sheet1", "D3", "内存利用率") 44 | f.SetCellValue("Sheet1", "E3", "硬盘状态") 45 | f.SetCellValue("Sheet1", "E4", "正常□\n异常□") 46 | f.SetRowHeight("Sheet1", 2, 32) 47 | f.SetRowHeight("Sheet1", 3, 32) 48 | f.SetCellValue("Sheet1", "F2", "基本安全\n检查") 49 | f.SetCellValue("Sheet1", "F3", "登录、系\n统安全") 50 | f.SetCellStyle("Sheet1", "F2", "F2", stylecenter) 51 | f.SetCellStyle("Sheet1", "F3", "F3", stylecenter) 52 | f.SetColWidth("Sheet1", "G", "G", 23.67) 53 | f.SetColWidth("Sheet1", "H", "H", 9.67) 54 | f.SetCellValue("Sheet1", "G2", "硬件检查") 55 | f.SetCellValue("Sheet1", "G3", "指示灯、电源、风扇情况") 56 | f.SetCellValue("Sheet1", "H2", "网卡检查") 57 | f.SetCellValue("Sheet1", "H3", "网卡状态") 58 | f.SetCellStyle("Sheet1", "H2", "H3", stylecenter) 59 | 60 | i := 4 61 | for i = 4; i < len(Insp)*3+4; { 62 | f.MergeCell("Sheet1", "B"+strconv.Itoa(i), "B"+strconv.Itoa(i+2)) 63 | f.MergeCell("Sheet1", "C"+strconv.Itoa(i), "C"+strconv.Itoa(i+2)) 64 | f.MergeCell("Sheet1", "D"+strconv.Itoa(i), "D"+strconv.Itoa(i+2)) 65 | f.MergeCell("Sheet1", "E"+strconv.Itoa(i), "E"+strconv.Itoa(i+2)) 66 | f.SetCellStyle("Sheet1", "E"+strconv.Itoa(i), "E"+strconv.Itoa(i+2), stylecenter) 67 | f.SetCellValue("Sheet1", "E"+strconv.Itoa(i), "正常□\n异常□") 68 | f.MergeCell("Sheet1", "F"+strconv.Itoa(i), "F"+strconv.Itoa(i+2)) 69 | f.SetCellStyle("Sheet1", "F"+strconv.Itoa(i), "F"+strconv.Itoa(i+2), stylecenter) 70 | f.SetCellValue("Sheet1", "F"+strconv.Itoa(i), "正常□\n异常□") 71 | f.SetCellValue("Sheet1", "G"+strconv.Itoa(i), "指示灯:正常□ 异常□") 72 | f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+1), "电源:正常□ 异常□") 73 | f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+2), "风扇:正常□ 异常□") 74 | f.MergeCell("Sheet1", "H"+strconv.Itoa(i), "H"+strconv.Itoa(i+2)) 75 | f.SetCellStyle("Sheet1", "H"+strconv.Itoa(i), "H"+strconv.Itoa(i+2), stylecenter) 76 | f.SetCellValue("Sheet1", "H"+strconv.Itoa(i), "正常□\n异常□") 77 | i = i + 3 78 | } 79 | 80 | for i := 0; i < len(Insp); { 81 | f.SetCellValue("Sheet1", "B"+strconv.Itoa(i*3+4), Insp[i].HostName) 82 | f.SetCellStyle("Sheet1", "B"+strconv.Itoa(i*3+4), "B"+strconv.Itoa(i*3+4), stylecenter) 83 | f.SetCellValue("Sheet1", "C"+strconv.Itoa(i*3+4), Insp[i].CPULoad) 84 | f.SetCellStyle("Sheet1", "C"+strconv.Itoa(i*3+4), "C"+strconv.Itoa(i*3+4), stylecenter) 85 | f.SetCellValue("Sheet1", "D"+strconv.Itoa(i*3+4), Insp[i].MemPct) 86 | f.SetCellStyle("Sheet1", "D"+strconv.Itoa(i*3+4), "D"+strconv.Itoa(i*3+4), stylecenter) 87 | i = i + 1 88 | } 89 | 90 | loc, _ := time.LoadLocation("Asia/Shanghai") 91 | StartUnix := time.Now().In(loc) 92 | StrStart := StartUnix.Format("2006-01-02 15:04:05") 93 | 94 | f.MergeCell("Sheet1", "A4", "A"+strconv.Itoa(i)) 95 | f.SetCellValue("Sheet1", "A4", groupname) 96 | f.SetColWidth("Sheet1", "A", "A", 10) 97 | f.SetCellStyle("Sheet1", "A4", "A"+strconv.Itoa(i), stylecenter) 98 | 99 | f.SetCellValue("Sheet1", "D"+strconv.Itoa(i+1), "巡检人员") 100 | f.SetCellValue("Sheet1", "F"+strconv.Itoa(i+1), "巡检日期") 101 | f.SetCellValue("Sheet1", "G"+strconv.Itoa(i+1), StrStart) 102 | f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+1), "早 □") 103 | f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+2), "中 □") 104 | f.SetCellValue("Sheet1", "H"+strconv.Itoa(i+3), "晚 □") 105 | 106 | f.SetActiveSheet(index) 107 | var b bytes.Buffer 108 | err = f.Write(&b) 109 | if err != nil { 110 | return []byte{}, nil 111 | } 112 | return b.Bytes(), nil 113 | } 114 | -------------------------------------------------------------------------------- /models/item_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //ItemList struct 4 | type ItemList struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items []Item `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | //ItemList struct 14 | type ItemRes struct { 15 | Code int `json:"code"` 16 | Message string `json:"message"` 17 | Data struct { 18 | Items interface{} `json:"items"` 19 | Total int64 `json:"total"` 20 | } `json:"data"` 21 | } 22 | 23 | //Item struct 24 | type Item struct { 25 | Itemid string `json:"itemid"` 26 | Type string `json:"type,"` 27 | SnmpCommunity string `json:"snmp_community,omitempty"` 28 | SnmpOid string `json:"snmp_oid,omitempty"` 29 | Hostid string `json:"hostid,"` 30 | Name string `json:"name,"` 31 | Key string `json:"key_,"` 32 | Delay string `json:"delay,"` 33 | History string `json:"history"` 34 | Trends string `json:"trends"` 35 | Lastvalue string `json:"lastvalue"` 36 | Lastclock string `json:"lastclock"` 37 | Prevvalue string `json:"prevvalue,omitempty"` 38 | State string `json:"state,omitempty"` 39 | Status string `json:"status,omitempty"` 40 | ValueType string `json:"value_type,omitempty"` 41 | TrapperHosts string `json:"trapper_hosts,omitempty"` 42 | Units string `json:"units,omitempty"` 43 | Snmpv3Securityname string `json:"snmpv3_securityname,omitempty"` 44 | Snmpv3Securitylevel string `json:"snmpv3_securitylevel,omitempty"` 45 | Snmpv3Authpassphrase string `json:"snmpv3_authpassphrase,omitempty"` 46 | Snmpv3Privpassphrase string `json:"snmpv3_privpassphrase,omitempty"` 47 | Snmpv3Authprotocol string `json:"snmpv3_authprotocol,omitempty"` 48 | Snmpv3Privprotocol string `json:"snmpv3_privprotocol,omitempty"` 49 | Snmpv3Contextname string `json:"snmpv3_contextname,omitempty"` 50 | Error string `json:"error,omitempty"` 51 | Lastlogsize string `json:"lastlogsize,omitempty"` 52 | Logtimefmt string `json:"logtimefmt,omitempty"` 53 | Templateid string `json:"templateid,omitempty"` 54 | Valuemapid string `json:"valuemapid,omitempty"` 55 | Params string `json:"params,omitempty"` 56 | IpmiSensor string `json:"ipmi_sensor,omitempty"` 57 | Authtype string `json:"authtype,omitempty"` 58 | Username string `json:"username,omitempty"` 59 | Password string `json:"password,omitempty"` 60 | Publickey string `json:"publickey,omitempty"` 61 | Privatekey string `json:"privatekey,omitempty"` 62 | Mtime string `json:"mtime,omitempty"` 63 | Lastns string `json:"lastns,omitempty"` 64 | Flags string `json:"flags,omitempty"` 65 | Interfaceid string `json:"interfaceid,omitempty"` 66 | Port string `json:"port,omitempty"` 67 | Description string `json:"description,omitempty"` 68 | InventoryLink string `json:"inventory_link,omitempty"` 69 | Lifetime string `json:"lifetime,omitempty"` 70 | Evaltype string `json:"evaltype,omitempty"` 71 | JmxEndpoint string `json:"jmx_endpoint,omitempty"` 72 | MasterItemid string `json:"master_itemid,omitempty"` 73 | Timeout string `json:"timeout,omitempty"` 74 | URL string `json:"url,omitempty"` 75 | QueryFields []interface{} `json:"query_fields,omitempty"` 76 | Posts string `json:"posts,omitempty"` 77 | StatusCodes string `json:"status_codes,omitempty"` 78 | FollowRedirects string `json:"follow_redirects,omitempty"` 79 | PostType string `json:"post_type,omitempty"` 80 | HTTPProxy string `json:"http_proxy,omitempty"` 81 | Headers []interface{} `json:"headers,omitempty"` 82 | RetrieveMode string `json:"retrieve_mode,omitempty"` 83 | RequestMethod string `json:"request_method,omitempty"` 84 | OutputFormat string `json:"output_format,omitempty"` 85 | SslCertFile string `json:"ssl_cert_file,omitempty"` 86 | SslKeyFile string `json:"ssl_key_file,omitempty"` 87 | SslKeyPassword string `json:"ssl_key_password,omitempty"` 88 | VerifyPeer string `json:"verify_peer,omitempty"` 89 | VerifyHost string `json:"verify_host,omitempty"` 90 | AllowTraps string `json:"allow_traps,omitempty"` 91 | } 92 | 93 | // item get all 94 | type Items struct { 95 | Itemid string `json:"itemid"` 96 | Name string `json:"name"` 97 | Key string `json:"key_"` 98 | } 99 | 100 | type ValueMap struct { 101 | Hostid string `json:"hostid"` 102 | Mappings []struct { 103 | Newvalue string `json:"newvalue"` 104 | Type string `json:"type"` 105 | Value string `json:"value"` 106 | } `json:"mappings"` 107 | Name string `json:"name"` 108 | UUID string `json:"uuid"` 109 | Valuemapid string `json:"valuemapid"` 110 | } 111 | -------------------------------------------------------------------------------- /models/mail.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "crypto/tls" 7 | "fmt" 8 | "github.com/astaxie/beego" 9 | "github.com/go-echarts/go-echarts/v2/opts" 10 | "github.com/jordan-wright/email" 11 | "html/template" 12 | "net/smtp" 13 | "os" 14 | template2 "zbxtable/utils" 15 | ) 16 | 17 | func Sendmail(To []string, Subject, attach string, temp []byte) error { 18 | from := beego.AppConfig.String("email_from") 19 | nickname := beego.AppConfig.String("email_nickname") 20 | secret := beego.AppConfig.String("email_secret") 21 | host := beego.AppConfig.String("email_host") 22 | port, _ := beego.AppConfig.Int("email_port") 23 | isSSL, _ := beego.AppConfig.Bool("email_isSSl") 24 | auth := smtp.PlainAuth("", from, secret, host) 25 | e := email.NewEmail() 26 | if nickname != "" { 27 | e.From = fmt.Sprintf("%s <%s>", nickname, from) 28 | } else { 29 | e.From = from 30 | } 31 | var err error 32 | file, err := os.Open(DowloadPath + attach) 33 | if err != nil { 34 | return err 35 | } 36 | attachment, err := e.Attach(bufio.NewReader(file), attach, "application/x-zip-compressed; charset=utf-8") 37 | if err != nil { 38 | return err 39 | } 40 | attachment.HTMLRelated = true 41 | e.Attachments[0] = attachment 42 | e.To = To 43 | e.Subject = Subject 44 | e.HTML = temp 45 | hostAddr := fmt.Sprintf("%s:%d", host, port) 46 | if isSSL { 47 | err = e.SendWithTLS(hostAddr, auth, &tls.Config{ServerName: host}) 48 | } else { 49 | err = e.Send(hostAddr, auth) 50 | } 51 | if err != nil { 52 | return err 53 | } 54 | return nil 55 | } 56 | 57 | type ItemsHtml struct { 58 | Title string `json:"message"` 59 | LinkName string `json:"linkname"` 60 | Start string `json:"start"` 61 | End string `json:"end"` 62 | EndLine string `json:"endLine"` 63 | TableInfo []TableDataList `json:"device"` 64 | } 65 | type TableDataList struct { 66 | Host string `json:"host"` 67 | IP string `json:"ip"` 68 | ItemName string `json:"itemname"` 69 | LinkBinWith string `json:"linkbinwith"` 70 | Avg string `json:"avg"` 71 | AVgPre string `json:"avgpre"` 72 | } 73 | 74 | func CreateMailTable(m Report, chartdata []ChartData) ([]byte, error) { 75 | var data ItemsHtml 76 | data.Title = m.Name 77 | data.LinkName = m.Name 78 | data.Start = chartdata[0].Start 79 | data.End = chartdata[0].End 80 | data.EndLine = "ZMS运维平台" 81 | var plist []TableDataList 82 | var one TableDataList 83 | for _, v := range chartdata { 84 | one.ItemName = v.Name 85 | one.IP = v.IP 86 | one.Host = v.Host 87 | one.LinkBinWith = template2.FormatTrafficFloat64(v.LinkBandWidth[0].Value.(float64)) 88 | ttt := Avg(v.Data) 89 | one.Avg = template2.FormatTrafficFloat64(Avg(v.Data)) 90 | one.AVgPre = AvgPer(ttt, v.LinkBandWidth[0].Value.(float64)) + "%" 91 | plist = append(plist, one) 92 | } 93 | data.TableInfo = plist 94 | t, err := template.New("webpage").Parse(htmlReport) 95 | if err != nil { 96 | return []byte{}, err 97 | } 98 | var buf bytes.Buffer 99 | err = t.Execute(&buf, data) 100 | if err != nil { 101 | return []byte{}, err 102 | } 103 | return buf.Bytes(), nil 104 | } 105 | func Avg(list []opts.LineData) (t float64) { 106 | var sum float64 107 | sum = float64(0) 108 | for _, v := range list { 109 | sum = sum + v.Value.(float64) 110 | } 111 | avg := sum / float64(len(list)) 112 | return avg 113 | } 114 | func AvgPer(dataavg, bind float64) string { 115 | //per := utils.Float64Round2(datasum / bind) 116 | per := fmt.Sprintf("%.2f", float64(dataavg)/float64(bind)*100) 117 | return per 118 | } 119 | -------------------------------------------------------------------------------- /models/problem.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | ) 6 | 7 | //ProblemsRes rest 8 | type ProblemsRes struct { 9 | Code int `json:"code"` 10 | Message string `json:"message"` 11 | Data struct { 12 | Items []Problems `json:"items"` 13 | Total int64 `json:"total"` 14 | } `json:"data"` 15 | } 16 | 17 | //Problems struct 18 | type Problems struct { 19 | Acknowledged string `json:"acknowledged"` 20 | Clock string `json:"clock"` 21 | Correlationid string `json:"correlationid"` 22 | Eventid string `json:"eventid"` 23 | Name string `json:"name"` 24 | Objectid string `json:"objectid"` 25 | Severity string `json:"severity"` 26 | } 27 | 28 | //GetProblems get porblems 29 | func GetProblems() ([]Problems, int64, error) { 30 | par := []string{"eventid"} 31 | problems, err := API.CallWithError("problem.get", Params{"output": "extend", 32 | "sortfield": par, 33 | "sortorder": "DESC"}) 34 | if err != nil { 35 | logs.Error(err) 36 | return []Problems{}, 0, err 37 | } 38 | hba, err := json.Marshal(problems.Result) 39 | if err != nil { 40 | logs.Error(err) 41 | return []Problems{}, 0, err 42 | } 43 | var hb []Problems 44 | err = json.Unmarshal(hba, &hb) 45 | if err != nil { 46 | logs.Error(err) 47 | return []Problems{}, 0, err 48 | } 49 | return hb, int64(len(hb)), err 50 | } 51 | -------------------------------------------------------------------------------- /models/report.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "strings" 7 | "time" 8 | "zbxtable/utils" 9 | 10 | "github.com/astaxie/beego/logs" 11 | "github.com/astaxie/beego/orm" 12 | ) 13 | 14 | // TableName alarm 15 | func (t *Report) TableName() string { 16 | return TableName("report") 17 | } 18 | 19 | // GetReportsByID f 20 | func GetReportsByID(id int) (v *Report, err error) { 21 | o := orm.NewOrm() 22 | v = &Report{ID: id} 23 | if err = o.Read(v); err == nil { 24 | return v, nil 25 | } 26 | return nil, err 27 | } 28 | 29 | // get all 30 | func GetALlReport() (cnt int64, system []Report, err error) { 31 | o := orm.NewOrm() 32 | var sys []Report 33 | al := new(Report) 34 | _, err = o.QueryTable(al).All(&sys) 35 | if err != nil { 36 | return 0, []Report{}, err 37 | } 38 | cnt = int64(len(sys)) 39 | return cnt, sys, nil 40 | } 41 | 42 | // GetAllTopology t 43 | func GetAllReportsLimt(page, limit, name string) (cnt int64, topo []Report, err error) { 44 | o := orm.NewOrm() 45 | var topologys []Report 46 | var CountTopologys []Report 47 | al := new(Report) 48 | pages, _ := strconv.Atoi(page) 49 | limits, _ := strconv.Atoi(limit) 50 | //count topology 51 | _, err = o.QueryTable(al).Filter("name__contains", name).All(&CountTopologys) 52 | if err != nil { 53 | return 0, []Report{}, err 54 | } 55 | _, err = o.QueryTable(al).Limit(limits, (pages-1)*limits).OrderBy("created_at"). 56 | Filter("name__contains", name).All(&topologys) 57 | if err != nil { 58 | logs.Debug(err) 59 | return 0, []Report{}, err 60 | } 61 | cnt = int64(len(CountTopologys)) 62 | return cnt, topologys, nil 63 | } 64 | 65 | // AddTopology insert a new ZmsTopology into database and returns 66 | // last inserted Id on success. 67 | func AddReport(m *Report) (id int64, err error) { 68 | o := orm.NewOrm() 69 | m.Items = utils.VAarToStr(m.Items) 70 | m.Cycle = utils.VAarToStr(m.Cycle) 71 | fmt.Println(m.Items, m.Cycle) 72 | id, err = o.Insert(m) 73 | if err != nil { 74 | logs.Debug(err) 75 | return 0, err 76 | } 77 | return id, err 78 | } 79 | 80 | // UpdateTopologyByID updates Alarm by Id and returns error if 81 | func UpdateReportByID(m *Report) (err error) { 82 | o := orm.NewOrm() 83 | v := Report{ID: m.ID} 84 | // ascertain id exists in the database 85 | err = o.Read(&v) 86 | if err != nil { 87 | return err 88 | } 89 | m.Items = utils.VAarToStr(m.Items) 90 | m.Cycle = utils.VAarToStr(m.Cycle) 91 | _, err = o.Update(m, "Name", "Emails", "Items", 92 | "LinkBandWidth", "Cycle", "Status", "Desc") 93 | if err != nil { 94 | return err 95 | } 96 | return nil 97 | } 98 | 99 | // UpdateTopologyByID updates Alarm by Id and returns error if 100 | func CheckNowByID(m *Report) (err error) { 101 | o := orm.NewOrm() 102 | v := Report{ID: m.ID} 103 | // ascertain id exists in the database 104 | err = o.Read(&v) 105 | if err != nil { 106 | return err 107 | } 108 | if len(v.Cycle) != 0 { 109 | cycle := strings.Split(v.Cycle, ",") 110 | for _, vv := range cycle { 111 | //week 112 | if vv == "week" { 113 | start := time.Now() 114 | err := TaskWeekReport(v) 115 | if err != nil { 116 | logs.Error(err) 117 | return err 118 | } 119 | //更新report状态 120 | v.ExecStatus = strconv.Itoa(Success) 121 | v.StartAt = start 122 | v.EndAt = time.Now() 123 | err = UpdateReportExecStatusByID(&v) 124 | if err != nil { 125 | logs.Error(err) 126 | return err 127 | } 128 | } 129 | //day 130 | if vv == "day" { 131 | start := time.Now() 132 | err := TaskDayReport(v) 133 | if err != nil { 134 | logs.Error(err) 135 | return err 136 | } 137 | //更新report状态 138 | v.ExecStatus = strconv.Itoa(Success) 139 | v.StartAt = start 140 | v.EndAt = time.Now() 141 | err = UpdateReportExecStatusByID(&v) 142 | if err != nil { 143 | logs.Error(err) 144 | return err 145 | } 146 | } 147 | } 148 | } 149 | return 150 | } 151 | 152 | // UpdateTopologyByID updates Alarm by Id and returns error if 153 | func UpdateReportExecStatusByID(m *Report) (err error) { 154 | o := orm.NewOrm() 155 | v := Report{ID: m.ID} 156 | // ascertain id exists in the database 157 | if err = o.Read(&v); err == nil { 158 | v.ExecStatus = m.ExecStatus 159 | v.StartAt = m.StartAt 160 | v.EndAt = m.EndAt 161 | _, err = o.Update(m, "ExecStatus", "StartAt", "EndAt") 162 | if err != nil { 163 | logs.Error(err) 164 | } 165 | } 166 | return 167 | } 168 | 169 | // UpdateTopologyEdgesByID updates Alarm by Id and returns error if 170 | func UpdateReportsStatusByID(m *Report) (err error) { 171 | o := orm.NewOrm() 172 | v := Report{ID: m.ID} 173 | // ascertain id exists in the database 174 | if err = o.Read(&v); err == nil { 175 | if v.Status == "0" { 176 | m.Status = "1" 177 | } else { 178 | m.Status = "0" 179 | } 180 | _, err = o.Update(m, "Status") 181 | if err != nil { 182 | logs.Error(err) 183 | } 184 | } 185 | return 186 | } 187 | 188 | // DeleteAlarm deletes Alarm by Id and returns error if 189 | // the record to be deleted doesn't exist 190 | func DeleteReport(id int) (err error) { 191 | o := orm.NewOrm() 192 | v := Report{ID: id} 193 | // ascertain id exists in the database 194 | if err = o.Read(&v); err == nil { 195 | var num int64 196 | if num, err = o.Delete(&Report{ID: id}); err == nil { 197 | logs.Debug("Number of records deleted in database:", num) 198 | } 199 | } 200 | return 201 | } 202 | -------------------------------------------------------------------------------- /models/rule.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | "zbxtable/utils" 7 | 8 | "github.com/astaxie/beego/orm" 9 | ) 10 | 11 | const ( 12 | RuleCust = iota + 1 13 | RuleDefault 14 | ) 15 | 16 | // AddRule one 17 | func AddRule(m *Rule) (id int64, err error) { 18 | o := orm.NewOrm() 19 | m.Sweek = utils.VAarToStr(m.Sweek) 20 | m.TenantID = utils.VAarToStr(m.TenantID) 21 | m.Channel = utils.VAarToStr(m.Channel) 22 | m.UserIds = utils.VAarToStr(m.UserIds) 23 | m.GroupIds = utils.VAarToStr(m.GroupIds) 24 | id, err = o.Insert(m) 25 | if err != nil { 26 | return 0, err 27 | } 28 | return id, nil 29 | } 30 | 31 | // GetRuleByID one 32 | func GetRuleByID(id int) (v *Rule, err error) { 33 | o := orm.NewOrm() 34 | v = &Rule{ID: id} 35 | if err = o.Read(v); err == nil { 36 | return v, nil 37 | } 38 | return nil, err 39 | } 40 | 41 | func GetRule(page, limit, name, tenant_id, m_type, status string) (cnt int64, userlist []Rule, err error) { 42 | o := orm.NewOrm() 43 | var rules []Rule 44 | var CountRules []Rule 45 | al := new(Rule) 46 | pages, _ := strconv.Atoi(page) 47 | limits, _ := strconv.Atoi(limit) 48 | //count alarms 49 | cond := orm.NewCondition() 50 | if name != "" { 51 | cond = cond.And("name__icontains", name) 52 | } 53 | if tenant_id != "" { 54 | cond = cond.And("tenant_id", tenant_id) 55 | } 56 | if m_type == "" { 57 | cond = cond.And("m_type", "1").Or("m_type", "2") 58 | } else { 59 | cond = cond.And("m_type", m_type) 60 | } 61 | if status != "" { 62 | cond = cond.And("status", status) 63 | } 64 | _, err = o.QueryTable(al).SetCond(cond). 65 | All(&CountRules) 66 | if err != nil { 67 | return 0, []Rule{}, err 68 | } 69 | _, err = o.QueryTable(al). 70 | Limit(limits, (pages-1)*limits).SetCond(cond). 71 | All(&rules, "id", "name", "conditions", "tenant_id", "note", 72 | "s_time", "e_time", "user_ids", "group_ids", "channel", "status", "created") 73 | if err != nil { 74 | return 0, []Rule{}, err 75 | } 76 | cnt = int64(len(CountRules)) 77 | return cnt, rules, nil 78 | } 79 | 80 | // UpdateRuleStatus rule 81 | func UpdateRuleStatus(m *Rule, tuser string) error { 82 | o := orm.NewOrm() 83 | //role检查 84 | p := Manager{Username: tuser} 85 | err := o.Read(&p, "username") 86 | if err != nil { 87 | return err 88 | } 89 | //not admin role return err 90 | if p.Role != "admin" { 91 | return errors.New("no permission") 92 | } 93 | //update 94 | v := Rule{ID: m.ID} 95 | err = o.Read(&v) 96 | if err != nil { 97 | return err 98 | } 99 | v.Status = m.Status 100 | _, err = o.Update(m, "Status") 101 | if err != nil { 102 | return err 103 | } 104 | return nil 105 | } 106 | 107 | // UpdateRule rule 108 | func UpdateRule(m *Rule, tuser string) error { 109 | o := orm.NewOrm() 110 | //role检查 111 | p := Manager{Username: tuser} 112 | err := o.Read(&p, "username") 113 | if err != nil { 114 | return err 115 | } 116 | //not admin role return err 117 | if p.Role != "admin" { 118 | return errors.New("no permission") 119 | } 120 | //update 121 | v := Rule{ID: m.ID} 122 | err = o.Read(&v) 123 | if err != nil { 124 | return err 125 | } 126 | //vue array to str 127 | m.TenantID = utils.VAarToStr(m.TenantID) 128 | m.Sweek = utils.VAarToStr(m.Sweek) 129 | m.Channel = utils.VAarToStr(m.Channel) 130 | m.UserIds = utils.VAarToStr(m.UserIds) 131 | m.GroupIds = utils.VAarToStr(m.GroupIds) 132 | _, err = o.Update(m, "name", "tenant_id", "conditions", "s_week", "m_type", 133 | "s_time", "e_time", "channel", "user_ids", "group_ids", "note", "status") 134 | if err != nil { 135 | return err 136 | } 137 | return nil 138 | } 139 | 140 | // DeleteRule status 141 | func DeleteRule(id int, tuser string) (err error) { 142 | o := orm.NewOrm() 143 | //role检查 144 | p := Manager{Username: tuser} 145 | err = o.Read(&p, "username") 146 | if err != nil { 147 | return err 148 | } 149 | //not admin role return err 150 | if p.Role != "admin" { 151 | return errors.New("no permission") 152 | } 153 | v := Rule{ID: id} 154 | 155 | // ascertain id exists in the database 156 | if err = o.Read(&v); err == nil { 157 | //default 规则不能删除 158 | if v.MType == "2" { 159 | return errors.New("默认规则不能删除") 160 | } 161 | _, err = o.Delete(&Rule{ID: id}) 162 | if err != nil { 163 | return err 164 | } 165 | return nil 166 | } 167 | return nil 168 | } 169 | -------------------------------------------------------------------------------- /models/rule_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Rule struct { 8 | ID int `orm:"column(id);auto" json:"id"` 9 | Name string `orm:"column(name);size(200);null" json:"name"` 10 | TenantID string `orm:"column(tenant_id);size(100);null" json:"tenant_id"` 11 | Conditions string `orm:"column(conditions);type(text);null" json:"conditions"` 12 | Sweek string `orm:"column(s_week);size(200);null" json:"s_week"` 13 | Stime string `orm:"column(s_time);size(200);null" json:"s_time"` 14 | Etime string `orm:"column(e_time);size(200);null" json:"e_time"` 15 | Channel string `orm:"column(channel);size(200);null" json:"channel"` 16 | UserIds string `orm:"column(user_ids);size(200);null" json:"user_ids"` 17 | GroupIds string `orm:"column(group_ids);size(200);null" json:"group_ids"` 18 | Note string `orm:"column(note);size(200);null" json:"note"` 19 | MType string `orm:"column(m_type);size(200);null" json:"m_type"` // 1告警分发 2.默认规则 3.屏蔽规则 4 20 | Status string `orm:"column(status);size(40);null" json:"status"` 21 | Created time.Time `orm:"column(created);type(datetime);null;auto_now_add;" json:"created"` 22 | Updated time.Time `orm:"column(updated);type(datetime);null;auto_now" json:"updated"` 23 | } 24 | type Conditions struct { 25 | RType string `orm:"column(r_type);size(200);null" json:"r_type"` 26 | RFunc string `orm:"column(r_func);size(200);null" json:"r_func"` 27 | Rvalue string `orm:"column(r_value);size(200);null" json:"r_value"` 28 | } 29 | type RuleResp struct { 30 | Code int `json:"code"` 31 | Message string `json:"message"` 32 | Data struct { 33 | Items interface{} `json:"items"` 34 | Total int64 `json:"total"` 35 | } `json:"data"` 36 | } 37 | 38 | //TableName alarm 39 | func (t *Rule) TableName() string { 40 | return TableName("rule") 41 | } 42 | -------------------------------------------------------------------------------- /models/session.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "compress/gzip" 5 | "context" 6 | "crypto/tls" 7 | "io" 8 | "net/http" 9 | "net/url" 10 | "os" 11 | "strings" 12 | 13 | "github.com/astaxie/beego" 14 | "github.com/astaxie/beego/logs" 15 | ) 16 | 17 | // Jar struct 18 | type Jar struct { 19 | cookies []*http.Cookie 20 | } 21 | 22 | // SetCookies a 23 | func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) { 24 | jar.cookies = cookies 25 | } 26 | 27 | // Cookies func 28 | func (jar *Jar) Cookies(u *url.URL) []*http.Cookie { 29 | return jar.cookies 30 | } 31 | 32 | // JAR st 33 | var JAR = new(Jar) 34 | 35 | // LoginZabbixWeb a 36 | func LoginZabbixWeb(ZabbixWeb, ZabbixUser, ZabbixPass string) { 37 | v := url.Values{} 38 | v.Set("name", ZabbixUser) 39 | v.Add("password", ZabbixPass) 40 | v.Add("autologin", "1") 41 | v.Add("enter", "Sign in") 42 | tr := &http.Transport{ 43 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 44 | } 45 | client := &http.Client{ 46 | Transport: tr, 47 | Jar: JAR, 48 | Timeout: 99999999999999, 49 | } 50 | request, err := http.NewRequest("POST", ZabbixWeb+"/index.php", strings.NewReader(v.Encode())) 51 | if err != nil { 52 | logs.Error("Fatal error ", err.Error()) 53 | return 54 | } 55 | request.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") 56 | request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") 57 | request.Header.Add("Accept-Encoding", "gzip, deflate") 58 | request.Header.Add("Accept-Language", "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3") 59 | request.Header.Add("Connection", "keep-alive") 60 | request.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0") 61 | response, err := client.Do(request) 62 | if err != nil { 63 | logs.Error("Fatal error ", err.Error()) 64 | return 65 | } 66 | defer response.Body.Close() 67 | if response.StatusCode == 200 { 68 | var reader io.Reader 69 | switch response.Header.Get("Content-Encoding") { 70 | case "gzip": 71 | reader, _ = gzip.NewReader(response.Body) 72 | default: 73 | reader = response.Body 74 | } 75 | data, err := io.ReadAll(reader) 76 | if err != nil { 77 | logs.Error("Failed to read response data: %+v", err) 78 | } 79 | //if beego.BConfig.RunMode == "dev" { 80 | // logs.Info("Login to zabbix response body is:", string(data)) 81 | //} 82 | if strings.Contains(string(data), "blocked") { 83 | logs.Error("Login to Zabbix failed!") 84 | os.Exit(1) 85 | } 86 | } else { 87 | os.Exit(1) 88 | } 89 | if beego.BConfig.RunMode == "dev" { 90 | logs.Info("Login to zabbix successfully!http status code:", response.StatusCode) 91 | } else { 92 | logs.Info("Login to zabbix successfully!") 93 | } 94 | //解析并把cookies存如redis 95 | u, err := url.Parse(ZabbixWeb) 96 | if err != nil { 97 | logs.Error("Failed to parse URL: %v", err) 98 | return 99 | } 100 | //把cookies设置到缓存中 101 | cookies := JAR.Cookies(u) // 从 CookieJar 中获取指定 URL 的 Cookies 102 | for _, cookie := range cookies { 103 | var ctx = context.Background() 104 | value, err := url.QueryUnescape(cookie.Value) 105 | if err != nil { 106 | logs.Error("解码失败:", err) 107 | return 108 | } 109 | err = RDB.Set(ctx, "zbx_session", value, 0).Err() 110 | if err != nil { 111 | logs.Error(err) 112 | return 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /models/system.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "time" 7 | 8 | "github.com/astaxie/beego/logs" 9 | "github.com/astaxie/beego/orm" 10 | ) 11 | 12 | // item link to inventory 13 | // link https://www.zabbix.com/documentation/current/en/manual/api/reference/host/object#host-inventory 14 | const ( 15 | Type = 1 16 | CPUCore = 16 17 | CPUUtilizationID = 18 18 | MemoryUtilizationID = 19 19 | MemoryTotalID = 20 20 | UptimeID = 22 21 | Model = 29 22 | //Add 20240221 23 | Ping = 57 24 | PingLoss = 58 25 | PingSec = 59 26 | 27 | //inventory 28 | OS = 5 29 | MemoryUsedID = 21 30 | DateHwInstall = 45 31 | DateHwExpiry = 46 32 | MACAddress = 12 33 | SerialNo = 8 34 | ResourceID = 9 35 | Location = 24 36 | Department = 51 37 | Vendor = 31 38 | ) 39 | 40 | // TableName alarm 41 | func (t *System) TableName() string { 42 | return TableName("system") 43 | } 44 | 45 | // GetSystemByID 根据id获取系统列表 46 | func GetSystemByID(id int64) (v *System, err error) { 47 | o := orm.NewOrm() 48 | v = &System{ID: id} 49 | if err = o.Read(v); err == nil { 50 | return v, nil 51 | } 52 | return nil, err 53 | } 54 | 55 | // GetALlSystem 获取所有系统列表 56 | func GetALlSystem() (cnt int64, system []System, err error) { 57 | o := orm.NewOrm() 58 | var sys []System 59 | al := new(System) 60 | _, err = o.QueryTable(al).All(&sys) 61 | if err != nil { 62 | return 0, []System{}, err 63 | } 64 | cnt = int64(len(sys)) 65 | return cnt, sys, nil 66 | } 67 | 68 | // UpdateSystem 更新系统分类及指标 69 | func UpdateSystem(m *System) (err error) { 70 | o := orm.NewOrm() 71 | v := System{ID: m.ID} 72 | err = o.Read(&v) 73 | if err != nil { 74 | return err 75 | } 76 | v.CPUCore = m.CPUCore 77 | v.CPUUtilizationID = m.CPUUtilizationID 78 | v.GroupID = m.GroupID 79 | v.MemoryTotalID = m.MemoryTotalID 80 | v.MemoryUsedID = m.MemoryUsedID 81 | v.MemoryUtilizationID = m.MemoryUtilizationID 82 | v.UptimeID = m.UptimeID 83 | v.Model = m.Model 84 | v.PingTemplateID = m.PingTemplateID 85 | m.UpdatedAt = time.Now() 86 | m.CreatedAt = v.CreatedAt 87 | _, err = o.Update(m, "CPUCore", "CPUUtilizationID", "GroupID", "MemoryTotalID", 88 | "MemoryUsedID", "MemoryUtilizationID", "UpdatedAt", "CreatedAt", "UptimeID", 89 | "Model", "PingTemplateID") 90 | if err != nil { 91 | return err 92 | } 93 | return nil 94 | } 95 | 96 | // SystemInit 初始化指标 97 | func SystemInit(id int64) error { 98 | o := orm.NewOrm() 99 | v := &System{ID: id} 100 | err := o.Read(v) 101 | if err != nil { 102 | return err 103 | } 104 | list := strings.Split(v.GroupID, ",") 105 | err = HostTypeSet(v, list) 106 | if err != nil { 107 | return err 108 | } 109 | vt := System{ID: id, Status: 1, InitedAt: time.Now()} 110 | _, err = o.Update(&vt, "status", "inited_at") 111 | if err != nil { 112 | return err 113 | } 114 | return nil 115 | } 116 | 117 | // HostTypeSet 根据提供的主机组初始化 118 | func HostTypeSet(s *System, groupId []string) error { 119 | //根据groupid获取host 120 | OutputPar := []string{"hostid"} 121 | rep, err := API.CallWithError("host.get", Params{ 122 | "output": OutputPar, 123 | "groupids": groupId}) 124 | if err != nil { 125 | return err 126 | } 127 | type hostData struct { 128 | HostID string `json:"hostid"` 129 | } 130 | var p []hostData 131 | resByre, resByteErr := json.Marshal(rep.Result) 132 | if resByteErr != nil { 133 | return err 134 | } 135 | err = json.Unmarshal(resByre, &p) 136 | if err != nil { 137 | return err 138 | } 139 | 140 | // 添加检查,如果没有找到主机则返回错误 141 | if len(p) == 0 { 142 | return fmt.Errorf("未在指定的主机组中找到任何主机") 143 | } 144 | 145 | //根据id主机类型 146 | var hType string 147 | switch s.ID { 148 | case 1: 149 | hType = "VM_LIN" 150 | case 2: 151 | hType = "VM_WIN" 152 | case 3: 153 | hType = "HW_NET" 154 | case 4: 155 | hType = "HW_SRV" 156 | default: 157 | hType = "VM_LIN" 158 | } 159 | //inventory 160 | InventoryPara := make(map[string]string) 161 | //主机类型直接写入,不关联监控指标 162 | InventoryPara["type"] = hType 163 | //开启主机Inventory为自动,并归类 164 | _, err = API.CallWithError("host.massupdate", Params{ 165 | "hosts": p, 166 | "inventory_mode": 1, 167 | "inventory": InventoryPara}) 168 | if err != nil { 169 | logs.Error(err) 170 | return err 171 | } 172 | //其他指标绑定 173 | inventoryItems := []struct { 174 | ID string 175 | Link int 176 | }{ 177 | {s.UptimeID, UptimeID}, 178 | {s.CPUCore, CPUCore}, 179 | {s.CPUUtilizationID, CPUUtilizationID}, 180 | {s.MemoryUtilizationID, MemoryUtilizationID}, 181 | {s.MemoryTotalID, MemoryTotalID}, 182 | {s.Model, Model}, 183 | } 184 | // Loop through the inventory items and bind each one 185 | for _, item := range inventoryItems { 186 | if item.ID == "" { 187 | continue 188 | } 189 | if err := ItemToInventory(item.ID, item.Link); err != nil { 190 | logs.Error(err) 191 | continue 192 | } 193 | } 194 | //ICMP 195 | if s.PingTemplateID == "" { 196 | return nil 197 | } 198 | ICMPToInventory(s.PingTemplateID) 199 | return nil 200 | } 201 | 202 | // ItemToInventory 指标绑定到类型 203 | func ItemToInventory(list string, inventoryId int) error { 204 | itemIDs := strings.Split(list, ",") 205 | for _, v := range itemIDs { 206 | _, err := API.CallWithError("item.update", Params{ 207 | "itemid": v, 208 | "inventory_link": inventoryId}) 209 | if err != nil { 210 | return err 211 | } 212 | } 213 | return nil 214 | } 215 | 216 | // ICMPToInventory queries ICMP metrics via the Zabbix API and associates them with the inventory 217 | func ICMPToInventory(id string) error { 218 | type itemData struct { 219 | ItemID string `json:"itemid"` 220 | Key string `json:"key_"` 221 | } 222 | 223 | rep, err := API.CallWithError("item.get", Params{ 224 | "output": []string{"itemid", "key_"}, 225 | "hostids": id, 226 | }) 227 | if err != nil { 228 | return err 229 | } 230 | 231 | resByre, resByteErr := json.Marshal(rep.Result) 232 | if resByteErr != nil { 233 | return err 234 | } 235 | var items []itemData 236 | if err := json.Unmarshal(resByre, &items); err != nil { 237 | return err 238 | } 239 | for _, item := range items { 240 | var inventoryLink int 241 | switch item.Key { 242 | case "icmpping": 243 | inventoryLink = Ping 244 | case "icmppingloss": 245 | inventoryLink = PingLoss 246 | case "icmppingsec": 247 | inventoryLink = PingSec 248 | default: 249 | continue 250 | } 251 | if _, err := API.CallWithError("item.update", Params{ 252 | "itemid": item.ItemID, 253 | "inventory_link": inventoryLink, 254 | }); err != nil { 255 | return err 256 | } 257 | } 258 | 259 | return nil 260 | } 261 | -------------------------------------------------------------------------------- /models/system_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | // system 6 | type System struct { 7 | ID int64 `orm:"column(id);auto" json:"id"` 8 | Name string `orm:"column(name);size(255)" json:"name"` 9 | GroupID string `orm:"column(group_id);size(255)" json:"group_id"` 10 | CPUUtilizationID string `orm:"column(cpu_utilization_id);size(200)" json:"cpu_utilization_id"` 11 | MemoryUtilizationID string `orm:"column(memory_utilization_id);size(200)" json:"memory_utilization_id"` 12 | MemoryUsedID string `orm:"column(memory_used_id);size(200)" json:"memory_used_id"` 13 | MemoryTotalID string `orm:"column(memory_total_id);size(200)" json:"memory_total_id"` 14 | UptimeID string `orm:"column(uptime_id);size(200)" json:"uptime_id"` 15 | CPUCore string `orm:"column(cpu_core);size(200)" json:"cpu_core"` 16 | Model string `orm:"model(cpu_core);size(200)" json:"model"` 17 | PingTemplateID string `orm:"column(ping_template_id);size(200)" json:"ping_template_id"` 18 | Ping string `orm:"column(ping);size(200)" json:"ping"` 19 | PingLoss string `orm:"column(ping_loss);size(200)" json:"ping_loss"` 20 | PingSec string `orm:"column(ping_sec);size(200)" json:"ping_sec"` 21 | InitedAt time.Time `orm:"column(inited_at);type(datetime);null" json:"inited_at"` 22 | CreatedAt time.Time `orm:"column(created_at);type(datetime);auto_now_add" json:"created_at"` 23 | UpdatedAt time.Time `orm:"column(updated_at);type(datetime);auto_now" json:"updated_at"` 24 | Status int `orm:"column(status);size(200)" json:"status"` 25 | } 26 | 27 | // SystemList struct 28 | type SystemList struct { 29 | Code int `json:"code"` 30 | Message string `json:"message"` 31 | Data struct { 32 | Items interface{} `json:"items"` 33 | Total int64 `json:"total"` 34 | } `json:"data"` 35 | } 36 | -------------------------------------------------------------------------------- /models/task_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "github.com/astaxie/beego/logs" 8 | "github.com/astaxie/beego/orm" 9 | ) 10 | 11 | type TaskLog struct { 12 | Id int `orm:"column(id);auto" json:"id"` 13 | ReportID int `orm:"column(report_id);default(0)" json:"report_id"` // 任务id 14 | Name string `orm:"column(name);varchar(200);null" json:"name"` // 任务名称 15 | Cycle string `orm:"column(cycle);varchar(64);null" json:"cycle"` // crontab 16 | StartTime time.Time `orm:"column(start_time);type(datetime);null" json:"start_time"` // 开始执行时间 17 | EndTime time.Time `orm:"column(end_time);type(datetime);null" json:"end_time"` // 执行完成(失败)时间 18 | Status int `orm:"column(status);default(0)" json:"status"` // 状态 0:执行失败 1:执行中 2:执行完毕 3:任务取消(上次任务未执行完成) 4:异步执行 19 | Result string `orm:"column(result);size(200);null" json:"result"` 20 | Files string `orm:"column(files);size(200);null" json:"files"` 21 | TotalTime int64 `orm:"column(total_time);default(0)" json:"total_time"` // 执行总时长 22 | } 23 | 24 | // SystemList struct 25 | type TaskRes struct { 26 | Code int `json:"code"` 27 | Message string `json:"message"` 28 | Data struct { 29 | Items interface{} `json:"items"` 30 | Total int64 `json:"total"` 31 | } `json:"data"` 32 | } 33 | 34 | // TableName alarm 35 | func (t *TaskLog) TableName() string { 36 | return TableName("task_log") 37 | } 38 | 39 | const ( 40 | NoBegin = iota 41 | Running 42 | Success 43 | Failed 44 | ) 45 | 46 | func CreateTaskLog(taskModel Report, status int) (int64, error) { 47 | taskLogModel := new(TaskLog) 48 | taskLogModel.ReportID = taskModel.ID 49 | taskLogModel.Name = taskModel.Name 50 | taskLogModel.Cycle = taskModel.Cycle 51 | taskLogModel.StartTime = time.Now() 52 | taskLogModel.Status = status 53 | insertId, err := taskLogModel.Create() 54 | return insertId, err 55 | } 56 | 57 | // AddTopology insert a new ZmsTopology into database and returns 58 | // last inserted Id on success. 59 | func (m *TaskLog) Create() (id int64, err error) { 60 | o := orm.NewOrm() 61 | id, err = o.Insert(m) 62 | if err != nil { 63 | logs.Debug(err) 64 | return 0, err 65 | } 66 | return id, err 67 | } 68 | 69 | func (taskLog *TaskLog) Update(m *Report) (int64, error) { 70 | // UpdateTopologyByID updates Alarm by Id and returns error if 71 | o := orm.NewOrm() 72 | v := Report{ID: m.ID} 73 | var err error 74 | // ascertain id exists in the database 75 | if err = o.Read(&v); err == nil { 76 | var num int64 77 | if num, err = o.Update(m); err == nil { 78 | logs.Debug("Number of records updated in database:", num) 79 | } 80 | return int64(m.ID), nil 81 | } 82 | return 0, err 83 | } 84 | 85 | func GetTaskLogList(page, limit, report_id string) (cnt int64, topo []TaskLog, err error) { 86 | o := orm.NewOrm() 87 | var tasklog []TaskLog 88 | var count []TaskLog 89 | al := new(TaskLog) 90 | pages, _ := strconv.Atoi(page) 91 | limits, _ := strconv.Atoi(limit) 92 | //count topology 93 | _, err = o.QueryTable(al).Filter("report_id", report_id).All(&count) 94 | _, err = o.QueryTable(al).Limit(limits, (pages-1)*limits).OrderBy("-start_time").Filter("report_id", report_id).All(&tasklog) 95 | if err != nil { 96 | logs.Debug(err) 97 | return 0, []TaskLog{}, err 98 | } 99 | cnt = int64(len(count)) 100 | return cnt, tasklog, nil 101 | } 102 | 103 | func (taskLog *TaskLog) Clear() (int64, error) { 104 | o := orm.NewOrm() 105 | al := new(TaskLog) 106 | id, err := o.QueryTable(al).Delete() 107 | if err != nil { 108 | logs.Debug(err) 109 | return 0, err 110 | } 111 | return id, err 112 | } 113 | 114 | //// 删除N个月前的日志 115 | //func (taskLog *TaskLog) Remove(id int) (int64, error) { 116 | // t := time.Now().AddDate(0, -id, 0) 117 | // return Db.Where("start_time <= ?", t.Format(DefaultTimeFormat)).Delete(taskLog) 118 | //} 119 | // 120 | //func (taskLog *TaskLog) Total(params CommonMap) (int64, error) { 121 | // session := Db.NewSession() 122 | // defer session.Close() 123 | // taskLog.parseWhere(session, params) 124 | // return session.Count(taskLog) 125 | //} 126 | 127 | // DeleteAlarm deletes Alarm by Id and returns error if 128 | // the record to be deleted doesn't exist 129 | func DeleteTaskLog(id int) (err error) { 130 | o := orm.NewOrm() 131 | v := TaskLog{Id: id} 132 | // ascertain id exists in the database 133 | if err = o.Read(&v); err == nil { 134 | _, err = o.Delete(&TaskLog{Id: id}) 135 | if err != nil { 136 | return err 137 | } 138 | return nil 139 | } 140 | return nil 141 | } 142 | -------------------------------------------------------------------------------- /models/template.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | "math" 6 | "strconv" 7 | "strings" 8 | ) 9 | 10 | // TemplateGet func 11 | func TemplateGet(page, limit, templates string) ([]Template, int64, error) { 12 | par := []string{"host", "name", "templateid"} 13 | hostspar := []string{"host", "name", "hostid"} 14 | rep, err := API.Call("template.get", Params{"output": par, 15 | "selectApplications": "count", "selectItems": "count", 16 | "selectTriggers": "count", "selectGraphs": "count", 17 | "selectDiscoveries": "count", "selectScreens": "count", 18 | "selectHosts": hostspar}) 19 | if err != nil { 20 | logs.Error(err) 21 | return []Template{}, 0, err 22 | } 23 | hba, err := json.Marshal(rep.Result) 24 | if err != nil { 25 | logs.Error(err) 26 | return []Template{}, 0, err 27 | } 28 | 29 | var hb []Template 30 | err = json.Unmarshal(hba, &hb) 31 | if err != nil { 32 | logs.Error(err) 33 | return []Template{}, 0, err 34 | } 35 | var dt []Template 36 | var d Template 37 | 38 | if templates != "" { 39 | for _, v := range hb { 40 | if strings.Contains(v.Name, templates) { 41 | d.Host = v.Host 42 | d.Templateid = v.Templateid 43 | d.Name = v.Name 44 | d.Hosts = v.Hosts 45 | d.Applications = v.Applications 46 | d.Triggers = v.Triggers 47 | d.Items = v.Items 48 | d.Graphs = v.Graphs 49 | d.Screens = v.Screens 50 | d.Discoveries = v.Discoveries 51 | dt = append(dt, d) 52 | } 53 | } 54 | } else { 55 | for _, v := range hb { 56 | d.Host = v.Host 57 | d.Templateid = v.Templateid 58 | d.Name = v.Name 59 | d.Hosts = v.Hosts 60 | d.Applications = v.Applications 61 | d.Triggers = v.Triggers 62 | d.Items = v.Items 63 | d.Graphs = v.Graphs 64 | d.Screens = v.Screens 65 | d.Discoveries = v.Discoveries 66 | dt = append(dt, d) 67 | } 68 | } 69 | 70 | IntPage, err := strconv.Atoi(page) 71 | if err != nil { 72 | IntPage = 1 73 | } 74 | IntLimit, err := strconv.Atoi(limit) 75 | if err != nil { 76 | IntLimit = 10 77 | } 78 | //如果dt为空直接返回 79 | if len(dt) == 0 { 80 | return dt, int64(len(dt)), err 81 | } 82 | //分页 83 | nums := len(dt) 84 | //page总数 85 | totalpages := int(math.Ceil(float64(nums) / float64(IntLimit))) 86 | if IntPage >= totalpages { 87 | IntPage = totalpages 88 | } 89 | if IntPage <= 0 { 90 | IntPage = 1 91 | } 92 | //结束页数据 93 | var end int 94 | //begin 开始页数据 95 | 96 | begin := (IntPage - 1) * IntLimit 97 | if IntPage == totalpages { 98 | end = nums 99 | } 100 | if IntPage < totalpages { 101 | end = IntPage * IntLimit 102 | } else { 103 | end = nums 104 | } 105 | //根据开始和结束返回数据列表 106 | var newtemplates []Template 107 | for i := begin; i < end; i++ { 108 | newtemplates = append(newtemplates, dt[i]) 109 | } 110 | return newtemplates, int64(len(dt)), err 111 | } 112 | 113 | // TemplateAllGet func 114 | func TemplateAllGet() ([]Template, int64, error) { 115 | par := []string{"host", "name", "templateid"} 116 | hostspar := []string{"host", "name", "hostid"} 117 | rep, err := API.Call("template.get", Params{"output": par, 118 | "selectApplications": "count", "selectItems": "count", 119 | "selectTriggers": "count", "selectGraphs": "count", 120 | "selectDiscoveries": "count", "selectScreens": "count", 121 | "selectHosts": hostspar}) 122 | if err != nil { 123 | return []Template{}, 0, err 124 | } 125 | hba, err := json.Marshal(rep.Result) 126 | if err != nil { 127 | return []Template{}, 0, err 128 | } 129 | 130 | var hb []Template 131 | err = json.Unmarshal(hba, &hb) 132 | if err != nil { 133 | return []Template{}, 0, err 134 | } 135 | return hb, int64(len(hb)), nil 136 | } 137 | 138 | // TemplateAllGet func 139 | func TemplateListGet() ([]TemplateByItemList, int64, error) { 140 | par := []string{"host", "name", "templateid"} 141 | rep, err := API.Call("template.get", Params{"output": par}) 142 | if err != nil { 143 | return []TemplateByItemList{}, 0, err 144 | } 145 | hba, err := json.Marshal(rep.Result) 146 | if err != nil { 147 | return []TemplateByItemList{}, 0, err 148 | } 149 | 150 | var hb []TemplateByItemList 151 | err = json.Unmarshal(hba, &hb) 152 | if err != nil { 153 | return []TemplateByItemList{}, 0, err 154 | } 155 | return hb, int64(len(hb)), nil 156 | } 157 | 158 | // TemplateAllGet func 159 | func TemplateByItem(templateid string) ([]TemplateByItemList, int64, error) { 160 | par := []string{"host", "name", "templateid"} 161 | itemParams := []string{"itemid", "name"} 162 | rep, err := API.Call("template.get", Params{"output": par, 163 | "templateids": templateid, 164 | "selectItems": itemParams, 165 | }) 166 | if err != nil { 167 | return []TemplateByItemList{}, 0, err 168 | } 169 | hba, err := json.Marshal(rep.Result) 170 | if err != nil { 171 | return []TemplateByItemList{}, 0, err 172 | } 173 | var hb []TemplateByItemList 174 | err = json.Unmarshal(hba, &hb) 175 | if err != nil { 176 | return []TemplateByItemList{}, 0, err 177 | } 178 | return hb, int64(len(hb)), nil 179 | } 180 | -------------------------------------------------------------------------------- /models/template_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //TemplateList struct 4 | type TemplateList struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items interface{} `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | //Template struct a 14 | type Template struct { 15 | Host string `json:"host"` 16 | Templateid string `json:"templateid"` 17 | Name string `json:"name"` 18 | Hosts []struct { 19 | Host string `json:"host"` 20 | Name string `json:"name"` 21 | HostID string `json:"hostid"` 22 | } `json:"hosts"` 23 | Applications string `json:"applications"` 24 | Triggers string `json:"triggers"` 25 | Items string `json:"items"` 26 | Graphs string `json:"graphs"` 27 | Screens string `json:"screens"` 28 | Discoveries string `json:"discoveries"` 29 | } 30 | 31 | //Template struct a 32 | type TemplateByItemList struct { 33 | Host string `json:"host"` 34 | Templateid string `json:"templateid"` 35 | Name string `json:"name"` 36 | Items []struct { 37 | ItemID string `json:"itemid"` 38 | Name string `json:"name"` 39 | } `json:"items"` 40 | } 41 | -------------------------------------------------------------------------------- /models/topodata.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "errors" 5 | "github.com/astaxie/beego/logs" 6 | "github.com/astaxie/beego/orm" 7 | "strings" 8 | "sync" 9 | "zbxtable/utils" 10 | ) 11 | 12 | // last inserted Id on success. 13 | func AddTopoData(m *TopologyData) (id int64, err error) { 14 | o := orm.NewOrm() 15 | id, err = o.Insert(m) 16 | if err != nil { 17 | return 0, err 18 | } 19 | return id, err 20 | } 21 | 22 | // GetAllTopology t 23 | func GetAllTopoData() (cnt int64, topodata []TopologyData, err error) { 24 | o := orm.NewOrm() 25 | var topologys []TopologyData 26 | al := new(TopologyData) 27 | //count topology 28 | _, err = o.QueryTable(al).OrderBy("-created_at").All(&topologys) 29 | if err != nil { 30 | logs.Debug(err) 31 | return 0, []TopologyData{}, err 32 | } 33 | cnt = int64(len(topologys)) 34 | return cnt, topologys, nil 35 | } 36 | 37 | //func UpdateLineData(v AEdge) { 38 | // //labels attr 39 | // v.Labels[0].Attrs.Label.Text = "" 40 | // v.Labels[0].Position.Angle = 0 41 | // v.Labels[0].Position.Offset = 20 42 | // v.Labels[0].Position.Options.EnsureLegibility = true 43 | // v.Labels[0].Position.Options.KeepGradient = true 44 | // //line attrs 45 | // v.Attrs.Line.StrokeWidth = 4 46 | // v.Attrs.Line.Stroke = "#A4A4A4" 47 | // v.Attrs.Line.StrokeDasharray = 0 48 | // if v.Attrs.Line.FlowID != "" { 49 | // GetFlowByFlowID(v.Attrs.Line.FlowID, &wg, flow) 50 | // v.Labels[0].Attrs.Label.Text = <-flow 51 | // } 52 | // //trigger get 53 | // if v.Attrs.Line.TriggerID != "" { 54 | // go GetTriggerValueByTriggerID(v.Attrs.Line.TriggerID, &wg, trigger) 55 | // status := <-trigger 56 | // switch { 57 | // //trigger正常 未告警 58 | // case status == "0": 59 | // v.Attrs.Line.Stroke = "#00FF00" 60 | // v.Attrs.Line.StrokeDasharray = 5 61 | // v.Attrs.Line.Style.Animation = "ant-line 30s infinite linear" 62 | // //trigger 告警 63 | // case status == "1": 64 | // v.Attrs.Line.Stroke = "#FF0000" 65 | // case status == "2": 66 | // v.Attrs.Line.Stroke = "#A4A4A4" 67 | // default: 68 | // v.Attrs.Line.Stroke = "#A4A4A4" 69 | // } 70 | // } 71 | // fmt.Println(v.Attrs.Line.Stroke) 72 | // aedge = append(aedge, v) 73 | //} 74 | ////go func() { 75 | //// wg.Wait() 76 | //// close(trigger) 77 | //// close(flow) 78 | ////}() 79 | ////wg.Wait() 80 | //fmt.Println("AAAA") 81 | //aedgestr, err := json.Marshal(aedge) 82 | //if err != nil { 83 | //logs.Debug(err) 84 | //return err 85 | //} 86 | //var Topo Topology 87 | //Topo.ID = v.ID 88 | //Topo.Edges = string(aedgestr) 89 | //err = UpdateTopologyEdgesByID(&Topo) 90 | //if err != nil { 91 | //logs.Debug(err) 92 | //return err 93 | //} 94 | 95 | func GetTriggerValueByTriggerID(TriggerID string) (value string, err error) { 96 | tri, err := GetTriggerValue(TriggerID) 97 | if err != nil || len(tri) == 0 { 98 | logs.Debug(err) 99 | return "2", err 100 | } 101 | return tri[0].Value, nil 102 | } 103 | 104 | func GetFlowByFlowID(FLowID string) (flow string, err error) { 105 | p, err := GetItemByID(FLowID) 106 | if err != nil { 107 | logs.Debug(err) 108 | return "", err 109 | } 110 | if len(p) == 0 { 111 | return "", errors.New("flow id is null") 112 | } else { 113 | //获取数据,判断是否为流量接口 114 | var NewItemKey string 115 | if strings.Contains(p[0].Name, "Bits sent") { 116 | NewkeyIN := strings.Replace(p[0].Key, "net.if.out", "net.if.in", -1) 117 | NewItemKey = strings.Replace(NewkeyIN, "Out", "In", -1) 118 | } 119 | if strings.Contains(p[0].Name, "Bits received") { 120 | NewkeyOut := strings.Replace(p[0].Key, "net.if.in", "net.if.out", -1) 121 | NewItemKey = strings.Replace(NewkeyOut, "In", "Out", -1) 122 | } 123 | NetItem, err := GetItemByKey(p[0].Hostid, NewItemKey) 124 | if err != nil { 125 | return "", err 126 | } 127 | flow = utils.FormatTraffic(NetItem[0].Lastvalue) + "/" + utils.FormatTraffic(p[0].Lastvalue) 128 | return flow, nil 129 | } 130 | } 131 | 132 | //host info 133 | func GetHostInfoByID(hostid string, wg *sync.WaitGroup, info chan string) { 134 | defer wg.Done() 135 | p, err := GetHostInfoTopology(hostid) 136 | if err != nil { 137 | logs.Debug(err) 138 | } 139 | StrP, err := json.Marshal(&p) 140 | if err != nil { 141 | logs.Debug(err) 142 | } 143 | info <- string(StrP) 144 | return 145 | } 146 | -------------------------------------------------------------------------------- /models/topodata_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | //TableName Topology 6 | func (t *TopologyData) TableName() string { 7 | return TableName("topology_data") 8 | } 9 | 10 | type TopologyData struct { 11 | ID int `orm:"column(id);auto" json:"id"` 12 | PID string `orm:"column(pid);size(60)" json:"pid"` 13 | VType string `orm:"column(v_type);size(60)" json:"v_type"` 14 | Type string `orm:"column(type);size(60)" json:"type"` 15 | TID string `orm:"column(tid);size(60)" json:"tid"` 16 | CreatedAt time.Time `orm:"column(created_at);auto_now_add;type(datetime)" json:"created_at"` 17 | UpdatedAt time.Time `orm:"column(updated_at);auto_now;type(datetime)" json:"updated_at"` 18 | } 19 | 20 | type AllEdge []AEdge 21 | 22 | type AEdge struct { 23 | Attrs struct { 24 | Line struct { 25 | FlowID string `json:"FlowID"` 26 | FlowName string `json:"FlowName"` 27 | FlowType string `json:"FlowType"` 28 | HostID string `json:"HostID"` 29 | HostName string `json:"HostName"` 30 | HostType string `json:"HostType"` 31 | HostValue string `json:"HostValue"` 32 | TriggerDesc string `json:"TriggerDesc"` 33 | TriggerID string `json:"TriggerID"` 34 | DataSource string `json:"dataSource"` 35 | InTape string `json:"inTape"` 36 | OutTape string `json:"outTape"` 37 | Stroke string `json:"stroke"` 38 | StrokeWidth int `json:"strokeWidth"` 39 | SourceMarker struct { 40 | Name string `json:"name"` 41 | Size int64 `json:"size"` 42 | Stroke string `json:"stroke"` 43 | } `json:"sourceMarker"` 44 | StrokeDasharray int64 `json:"strokeDasharray"` 45 | Style struct { 46 | Animation string `json:"animation"` 47 | } `json:"style"` 48 | TargetMarker struct { 49 | Name string `json:"name"` 50 | Size int64 `json:"size"` 51 | } `json:"targetMarker"` 52 | } `json:"line"` 53 | } `json:"attrs"` 54 | Connector string `json:"connector"` 55 | ID string `json:"id"` 56 | Labels []struct { 57 | Attrs struct { 58 | Label struct { 59 | Text string `json:"text"` 60 | } `json:"label"` 61 | } `json:"attrs"` 62 | Position struct { 63 | Distance string `json:"distance"` 64 | Offset float64 `json:"offset"` 65 | Angle int `json:"angle"` 66 | Options struct { 67 | KeepGradient bool `json:"keepGradient"` 68 | EnsureLegibility bool `json:"ensureLegibility"` 69 | } `json:"options"` 70 | } `json:"position"` 71 | } `json:"labels"` 72 | Router struct { 73 | Name string `json:"name"` 74 | } `json:"router"` 75 | Shape string `json:"shape"` 76 | Source struct { 77 | Cell string `json:"cell"` 78 | Port string `json:"port"` 79 | } `json:"source"` 80 | Target struct { 81 | Cell string `json:"cell"` 82 | Port string `json:"port"` 83 | } `json:"target"` 84 | ZIndex int64 `json:"zIndex"` 85 | } 86 | 87 | type AllNodes []PNodes 88 | 89 | type PNodes struct { 90 | Attrs struct { 91 | Image struct { 92 | Xlink_href string `json:"xlink:href"` 93 | } `json:"image"` 94 | Label struct { 95 | HostID string `json:"HostID"` 96 | HostType string `json:"HostType"` 97 | HostValue string `json:"HostValue"` 98 | HostCPU string `json:"HostCPU"` 99 | HostMem string `json:"HostMem"` 100 | HostAlarm string `json:"HostAlarm"` 101 | HostClock string `json:"HostClock"` 102 | HostStatus string `json:"HostStatus"` 103 | HostError string `json:"HostError"` 104 | Text string `json:"text"` 105 | } `json:"label"` 106 | Text struct { 107 | Text string `json:"text"` 108 | } `json:"text"` 109 | } `json:"attrs"` 110 | ID string `json:"id"` 111 | Ports struct { 112 | Groups struct { 113 | Bottom struct { 114 | Attrs struct { 115 | Circle struct { 116 | Fill string `json:"fill"` 117 | Magnet bool `json:"magnet"` 118 | R int64 `json:"r"` 119 | Stroke string `json:"stroke"` 120 | StrokeWidth int64 `json:"strokeWidth"` 121 | } `json:"circle"` 122 | } `json:"attrs"` 123 | Position string `json:"position"` 124 | } `json:"bottom"` 125 | Left struct { 126 | Attrs struct { 127 | Circle struct { 128 | Fill string `json:"fill"` 129 | Magnet bool `json:"magnet"` 130 | R int64 `json:"r"` 131 | Stroke string `json:"stroke"` 132 | StrokeWidth int64 `json:"strokeWidth"` 133 | } `json:"circle"` 134 | } `json:"attrs"` 135 | Position string `json:"position"` 136 | } `json:"left"` 137 | Right struct { 138 | Attrs struct { 139 | Circle struct { 140 | Fill string `json:"fill"` 141 | Magnet bool `json:"magnet"` 142 | R int64 `json:"r"` 143 | Stroke string `json:"stroke"` 144 | StrokeWidth int64 `json:"strokeWidth"` 145 | } `json:"circle"` 146 | } `json:"attrs"` 147 | Position string `json:"position"` 148 | } `json:"right"` 149 | Top struct { 150 | Attrs struct { 151 | Circle struct { 152 | Fill string `json:"fill"` 153 | Magnet bool `json:"magnet"` 154 | R int64 `json:"r"` 155 | Stroke string `json:"stroke"` 156 | StrokeWidth int64 `json:"strokeWidth"` 157 | } `json:"circle"` 158 | } `json:"attrs"` 159 | Position string `json:"position"` 160 | } `json:"top"` 161 | } `json:"groups"` 162 | Items []struct { 163 | Group string `json:"group"` 164 | ID string `json:"id"` 165 | } `json:"items"` 166 | //Style struct { 167 | // Visibility bool `json:"visibility"` 168 | //} `json:"style"` 169 | } `json:"ports"` 170 | Position struct { 171 | X int64 `json:"x"` 172 | Y int64 `json:"y"` 173 | } `json:"position"` 174 | Shape string `json:"shape"` 175 | Size struct { 176 | Height int64 `json:"height"` 177 | Width int64 `json:"width"` 178 | } `json:"size"` 179 | ZIndex int64 `json:"zIndex"` 180 | } 181 | -------------------------------------------------------------------------------- /models/topology_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Topology struct { 6 | ID int `orm:"column(id);auto" json:"id"` 7 | Nodes string `orm:"column(nodes);type(text)" json:"nodes"` 8 | Edges string `orm:"column(edges);type(text)" json:"edges"` 9 | Topology string `orm:"column(topology);size(200)" json:"topology"` 10 | Status string `orm:"column(status);size(10)" json:"status"` 11 | CreatedAt time.Time `orm:"column(created_at);auto_now_add;type(datetime)" json:"created_at"` 12 | UpdatedAt time.Time `orm:"column(updated_at);auto_now;type(datetime)" json:"updated_at"` 13 | } 14 | 15 | //TableName Topology 16 | func (t *Topology) TableName() string { 17 | return TableName("topology") 18 | } 19 | 20 | //TopologyList struct 21 | type TopologyList struct { 22 | Code int `json:"code"` 23 | Message string `json:"message"` 24 | Data struct { 25 | Items []Topology `json:"items"` 26 | Total int64 `json:"total"` 27 | } `json:"data"` 28 | } 29 | 30 | //TopologyList struct 31 | type TopologyInfo struct { 32 | Code int `json:"code"` 33 | Message string `json:"message"` 34 | Data struct { 35 | Items *Topology `json:"items"` 36 | Total int64 `json:"total"` 37 | } `json:"data"` 38 | } 39 | 40 | type AutoGenerated struct { 41 | Message string `json:"message"` 42 | Status int `json:"status"` 43 | Data struct { 44 | Nodes []struct { 45 | ID string `json:"id"` 46 | Size int `json:"size"` 47 | Label string `json:"label"` 48 | Text string `json:"text"` 49 | IsCenter bool `json:"isCenter"` 50 | SiteFlag string `json:"siteFlag"` 51 | IsClick bool `json:"isClick"` 52 | Style struct { 53 | Fill string `json:"fill"` 54 | Opacity int `json:"opacity"` 55 | FillOpacity int `json:"fillOpacity"` 56 | Cursor string `json:"cursor"` 57 | } `json:"style,omitempty"` 58 | LabelCfg struct { 59 | Style struct { 60 | Fill string `json:"fill"` 61 | FontSize int `json:"fontSize"` 62 | } `json:"style"` 63 | Position string `json:"position"` 64 | Offset []int `json:"offset"` 65 | } `json:"labelCfg,omitempty"` 66 | BackgroundConfig struct { 67 | Fill string `json:"fill"` 68 | Padding []int `json:"padding"` 69 | Radius int `json:"radius"` 70 | } `json:"backgroundConfig"` 71 | IsFisrtNodes bool `json:"isFisrtNodes,omitempty"` 72 | } `json:"nodes"` 73 | Edges []struct { 74 | Source string `json:"source"` 75 | Target string `json:"target"` 76 | Type string `json:"type"` 77 | Label string `json:"label"` 78 | LineNum int `json:"lineNum"` 79 | } `json:"edges"` 80 | } `json:"data"` 81 | } 82 | 83 | type Nodes struct { 84 | ID string `json:"id"` 85 | InternalName string `json:"internal_name"` 86 | Label string `json:"label"` 87 | Text string `json:"text"` 88 | X string `json:"x"` 89 | Y string `json:"y"` 90 | Type string `json:"type"` 91 | Img string `json:"img"` 92 | } 93 | type Edges struct { 94 | Source string `json:"source"` 95 | Target string `json:"target"` 96 | Type string `json:"type"` 97 | Label string `json:"label"` 98 | LineNum int `json:"lineNum"` 99 | Style struct { 100 | LineWidth int `json:"lineWidth"` 101 | Stroke string `json:"stroke"` 102 | StartArrow bool `json:"startArrow"` 103 | EndArrow bool `json:"endArrow"` 104 | } `json:"style,"` 105 | } 106 | 107 | type Data struct { 108 | Nodes []Nodes `json:"nodes"` 109 | Edges []Edges `json:"edges"` 110 | } 111 | -------------------------------------------------------------------------------- /models/trend.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | ) 6 | 7 | //GetTrendByItemID by itemid limit 8 | func GetTrendByItemID(itemid string, limit string) ([]Trend, error) { 9 | par := []string{"itemid", "clock", "num", "value_min", "value_avg", "value_max"} 10 | par1 := []string{itemid} 11 | rep, err := API.Call("trend.get", Params{"output": par, 12 | "itemids": par1, "limit": limit}) 13 | if err != nil { 14 | logs.Error(err) 15 | return []Trend{}, err 16 | } 17 | hba, err := json.Marshal(rep.Result) 18 | if err != nil { 19 | logs.Error(err) 20 | return []Trend{}, err 21 | } 22 | var hb []Trend 23 | err = json.Unmarshal(hba, &hb) 24 | if err != nil { 25 | logs.Error(err) 26 | return []Trend{}, err 27 | } 28 | return hb, err 29 | } 30 | 31 | //GetTrendData by itemid limit 32 | func GetTrendData(itemid, timefrom, timetill string) ([]Trend, error) { 33 | output := []string{"itemid", "clock", "num", "value_min", "value_avg", "value_max"} 34 | itemids := []string{itemid} 35 | rep, err := API.Call("trend.get", Params{"output": output, "time_from": timefrom, 36 | "time_till": timetill, "itemids": itemids}) 37 | if err != nil { 38 | logs.Error(err) 39 | return []Trend{}, err 40 | } 41 | hba, err := json.Marshal(rep.Result) 42 | if err != nil { 43 | logs.Error(err) 44 | return []Trend{}, err 45 | } 46 | var hb []Trend 47 | err = json.Unmarshal(hba, &hb) 48 | if err != nil { 49 | logs.Error(err) 50 | return []Trend{}, err 51 | } 52 | return hb, err 53 | } 54 | 55 | //GetTrendDataByItemid by itemid limit 56 | func GetTrendDataByItemid(item Item, time_from, time_till int64) ([]Trend, error) { 57 | output := []string{"itemid", "clock", "num", "value_min", "value_avg", "value_max"} 58 | itemids := []string{item.Itemid} 59 | rep, err := API.CallWithError("trend.get", 60 | Params{"output": output, 61 | "time_from": time_from, 62 | "time_till": time_till, 63 | "itemids": itemids}) 64 | if err != nil { 65 | logs.Error(err) 66 | return []Trend{}, err 67 | } 68 | hba, err := json.Marshal(rep.Result) 69 | if err != nil { 70 | logs.Error(err) 71 | return []Trend{}, err 72 | } 73 | var hb []Trend 74 | err = json.Unmarshal(hba, &hb) 75 | if err != nil { 76 | logs.Error(err) 77 | return []Trend{}, err 78 | } 79 | return hb, err 80 | } 81 | -------------------------------------------------------------------------------- /models/trend_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //TrendList struct 4 | type TrendList struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items []Trend `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | //Trend struct 14 | type Trend struct { 15 | Itemid string `json:"itemid"` 16 | Clock string `json:"clock"` 17 | Num string `json:"num"` 18 | ValueMin string `json:"value_min"` 19 | ValueAvg string `json:"value_avg"` 20 | ValueMax string `json:"value_max"` 21 | } 22 | -------------------------------------------------------------------------------- /models/trigger.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/astaxie/beego/logs" 5 | "strconv" 6 | ) 7 | 8 | //GetTriggers get porblems 9 | func GetTriggers() ([]EndTrigger, int64, error) { 10 | par11 := []string{"hostid", "name"} 11 | filter := make(map[string]string) 12 | filter["value"] = "1" 13 | triggers, err := API.CallWithError("trigger.get", Params{"output": "extend", 14 | "sortfield": "lastchange", 15 | "sortorder": "DESC", 16 | "selectHosts": par11, 17 | "selectLastEvent": "extend", 18 | "filter": filter, 19 | "maintenance": false, 20 | "only_true": true, 21 | "monitored": true}) 22 | if err != nil { 23 | logs.Debug(err) 24 | return []EndTrigger{}, 0, err 25 | } 26 | hba, err := json.Marshal(triggers.Result) 27 | if err != nil { 28 | logs.Debug(err) 29 | return []EndTrigger{}, 0, err 30 | } 31 | var hb []LastTriggers 32 | err = json.Unmarshal(hba, &hb) 33 | if err != nil { 34 | logs.Debug(err) 35 | return []EndTrigger{}, 0, err 36 | } 37 | var bs EndTrigger 38 | var ma []EndTrigger 39 | for _, v := range hb { 40 | bs.Acknowledged = v.LastEvent.Acknowledged 41 | bs.Hostid = v.Hosts[0].Hostid 42 | bs.Name = v.Hosts[0].Name 43 | bs.Lastchange = v.Lastchange 44 | bs.LastEventName = v.LastEvent.Name 45 | bs.Severity = v.LastEvent.Severity 46 | bs.Eventid = v.LastEvent.Eventid 47 | bs.Objectid = v.LastEvent.Objectid 48 | ma = append(ma, bs) 49 | } 50 | return ma, int64(len(ma)), nil 51 | } 52 | 53 | //GetTriggerList get porblems 54 | func GetTriggerList(hostid string) ([]TriggerListStr, int64, error) { 55 | //par11 := []string{"hostid", "name"} 56 | //filter := make(map[string]string) 57 | //filter["value"] = "1" 58 | triggers, err := API.CallWithError("trigger.get", Params{"output": "extend", 59 | "sortorder": "DESC", 60 | "hostids": hostid, 61 | "monitored": true, 62 | "expandDescription": true}) 63 | if err != nil { 64 | logs.Debug(err) 65 | return []TriggerListStr{}, 0, err 66 | } 67 | hba, err := json.Marshal(triggers.Result) 68 | if err != nil { 69 | logs.Debug(err) 70 | return []TriggerListStr{}, 0, err 71 | } 72 | var hb []TriggerListStr 73 | err = json.Unmarshal(hba, &hb) 74 | if err != nil { 75 | logs.Debug(err) 76 | return []TriggerListStr{}, 0, err 77 | } 78 | return hb, int64(len(hb)), nil 79 | } 80 | 81 | //GetTriggerList get porblems 82 | func GetTriggerHostCount(hostid string) (int64, error) { 83 | filter := make(map[string]string) 84 | filter["value"] = "1" 85 | triggers, err := API.CallWithError("trigger.get", Params{"output": "extend", 86 | "hostids": hostid, 87 | "filter": filter, 88 | "maintenance": false, 89 | "only_true": true, 90 | "countOutput": true, 91 | "monitored": true}) 92 | if err != nil { 93 | logs.Debug(err) 94 | return 0, err 95 | } 96 | CountTrigger := triggers.Result.(string) 97 | count, err := strconv.ParseInt(CountTrigger, 10, 64) 98 | if err != nil { 99 | return 0, err 100 | } 101 | return count, nil 102 | } 103 | 104 | //GetTriggerList get porblems 105 | func GetTriggerValue(triggerid string) ([]TriggerListStr, error) { 106 | OutputPar := []string{"value", "status", "state", "description"} 107 | triggers, err := API.CallWithError("trigger.get", Params{"output": OutputPar, 108 | "triggerids": triggerid}) 109 | if err != nil { 110 | logs.Debug(err) 111 | return []TriggerListStr{}, err 112 | } 113 | hba, err := json.Marshal(triggers.Result) 114 | if err != nil { 115 | logs.Debug(err) 116 | return []TriggerListStr{}, err 117 | } 118 | var hb []TriggerListStr 119 | err = json.Unmarshal(hba, &hb) 120 | if err != nil { 121 | logs.Debug(err) 122 | return []TriggerListStr{}, err 123 | } 124 | return hb, nil 125 | } 126 | -------------------------------------------------------------------------------- /models/trigger_mod.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | //TriggersRes rest 4 | type TriggersRes struct { 5 | Code int `json:"code"` 6 | Message string `json:"message"` 7 | Data struct { 8 | Items []EndTrigger `json:"items"` 9 | Total int64 `json:"total"` 10 | } `json:"data"` 11 | } 12 | 13 | //TriggersRes rest 14 | type TriggersListRes struct { 15 | Code int `json:"code"` 16 | Message string `json:"message"` 17 | Data struct { 18 | Items []TriggerListStr `json:"items"` 19 | Total int64 `json:"total"` 20 | } `json:"data"` 21 | } 22 | 23 | //LastTriggers struct 24 | type LastTriggers struct { 25 | Comments string `json:"comments"` 26 | CorrelationMode string `json:"correlation_mode"` 27 | CorrelationTag string `json:"correlation_tag"` 28 | Description string `json:"description"` 29 | Details string `json:"details"` 30 | Error string `json:"error"` 31 | Expression string `json:"expression"` 32 | Flags string `json:"flags"` 33 | Hosts []struct { 34 | Hostid string `json:"hostid"` 35 | Name string `json:"name"` 36 | } `json:"hosts"` 37 | LastEvent struct { 38 | Acknowledged string `json:"acknowledged"` 39 | Clock string `json:"clock"` 40 | Eventid string `json:"eventid"` 41 | Name string `json:"name"` 42 | Ns string `json:"ns"` 43 | Object string `json:"object"` 44 | Objectid string `json:"objectid"` 45 | Severity string `json:"severity"` 46 | Source string `json:"source"` 47 | Value string `json:"value"` 48 | } `json:"lastEvent"` 49 | Lastchange string `json:"lastchange"` 50 | ManualClose string `json:"manual_close"` 51 | Priority string `json:"priority"` 52 | RecoveryExpression string `json:"recovery_expression"` 53 | RecoveryMode string `json:"recovery_mode"` 54 | State string `json:"state"` 55 | Status string `json:"status"` 56 | Templateid string `json:"templateid"` 57 | Triggerid string `json:"triggerid"` 58 | Type string `json:"type"` 59 | URL string `json:"url"` 60 | Value string `json:"value"` 61 | } 62 | 63 | //LastTriggers struct 64 | type TriggerListStr struct { 65 | Comments string `json:"comments"` 66 | CorrelationMode string `json:"correlation_mode"` 67 | CorrelationTag string `json:"correlation_tag"` 68 | Description string `json:"description"` 69 | Details string `json:"details"` 70 | Error string `json:"error"` 71 | Expression string `json:"expression"` 72 | Flags string `json:"flags"` 73 | Lastchange string `json:"lastchange"` 74 | ManualClose string `json:"manual_close"` 75 | Priority string `json:"priority"` 76 | RecoveryExpression string `json:"recovery_expression"` 77 | RecoveryMode string `json:"recovery_mode"` 78 | State string `json:"state"` 79 | Status string `json:"status"` 80 | Templateid string `json:"templateid"` 81 | Triggerid string `json:"triggerid"` 82 | Type string `json:"type"` 83 | URL string `json:"url"` 84 | Value string `json:"value"` 85 | } 86 | 87 | //EndTrigger struct 88 | type EndTrigger struct { 89 | Acknowledged string `json:"acknowledged"` 90 | Hostid string `json:"hostid"` 91 | Name string `json:"name"` 92 | Lastchange string `json:"lastchange"` 93 | LastEventName string `json:"lasteventname"` 94 | Severity string `json:"severity"` 95 | Eventid string `json:"eventid"` 96 | Objectid string `json:"objectid"` 97 | } 98 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 8088; 3 | server_name localhost; 4 | root /usr/local/zbxtable/web; 5 | location /v1 { 6 | proxy_set_header X-Forwarded-For $remote_addr; 7 | proxy_set_header Host $http_host; 8 | proxy_pass http://127.0.0.1:8085; 9 | } 10 | location /ws/ { 11 | proxy_pass http://127.0.0.1:8085; 12 | proxy_http_version 1.1; 13 | proxy_pass_header Server; 14 | proxy_redirect off; 15 | proxy_set_header Upgrade $http_upgrade; 16 | proxy_set_header Connection "upgrade"; 17 | proxy_set_header Host $host; 18 | } 19 | location /download { 20 | root /usr/local/zbxtable; 21 | } 22 | location / { 23 | try_files $uri /index.html; 24 | } 25 | } -------------------------------------------------------------------------------- /routers/router.go: -------------------------------------------------------------------------------- 1 | // routers init 2 | // @APIVersion 1.0.0 3 | // @Title ZMS API 4 | // @Description ZMS API 5 | // @License Apache 2.0 6 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 7 | 8 | package routers 9 | 10 | import ( 11 | "zbxtable/controllers" 12 | 13 | "github.com/astaxie/beego" 14 | "github.com/astaxie/beego/plugins/cors" 15 | ) 16 | 17 | // RouterInit router 18 | func RouterInit() { 19 | beego.SetStaticPath("/download", "download") 20 | //dev mod 21 | if beego.BConfig.RunMode == "dev" { 22 | beego.BConfig.WebConfig.DirectoryIndex = true 23 | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" 24 | beego.SetStaticPath("/static", "static") 25 | } 26 | beego.Router("/ws/:id", &controllers.WebSocketController{}) 27 | beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{ 28 | AllowAllOrigins: true, 29 | AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, 30 | AllowHeaders: []string{"Origin", "X-Token", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"}, 31 | ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"}, 32 | AllowCredentials: true, 33 | })) 34 | ns := beego.NewNamespace("/v1", 35 | beego.NSRouter("/login", &controllers.BeforeUserController{}, "*:Login"), 36 | beego.NSRouter("/logout", &controllers.BeforeUserController{}, "*:Logout"), 37 | beego.NSRouter("/receive", &controllers.BeforeUserController{}, "*:Receive"), 38 | beego.NSRouter("/webhook", &controllers.BeforeUserController{}, "*:Webhook"), 39 | beego.NSNamespace("/index", 40 | beego.NSInclude( 41 | &controllers.IndexController{}, 42 | ), 43 | ), 44 | beego.NSNamespace("/alarm", 45 | beego.NSInclude( 46 | &controllers.AlarmController{}, 47 | ), 48 | ), 49 | beego.NSNamespace("/problem", 50 | beego.NSInclude( 51 | &controllers.ProblemsController{}, 52 | ), 53 | ), 54 | beego.NSNamespace("/trigger", 55 | beego.NSInclude( 56 | &controllers.TriggersController{}, 57 | ), 58 | ), 59 | beego.NSNamespace("/export", 60 | beego.NSInclude( 61 | &controllers.ExpController{}, 62 | ), 63 | ), 64 | beego.NSNamespace("/host", 65 | beego.NSInclude( 66 | &controllers.HostController{}, 67 | ), 68 | ), 69 | beego.NSNamespace("/host_group", 70 | beego.NSInclude( 71 | &controllers.HostGroupsController{}, 72 | ), 73 | ), 74 | beego.NSNamespace("/template", 75 | beego.NSInclude( 76 | &controllers.TemplateController{}, 77 | ), 78 | ), 79 | beego.NSNamespace("/item", 80 | beego.NSInclude( 81 | &controllers.ItemController{}, 82 | ), 83 | ), 84 | beego.NSNamespace("/history", 85 | beego.NSInclude( 86 | &controllers.HistoryController{}, 87 | ), 88 | ), 89 | beego.NSNamespace("/trend", 90 | beego.NSInclude( 91 | &controllers.TrendController{}, 92 | ), 93 | ), 94 | beego.NSNamespace("/graph", 95 | beego.NSInclude( 96 | &controllers.GraphController{}, 97 | ), 98 | ), 99 | beego.NSNamespace("/images", 100 | beego.NSInclude( 101 | &controllers.ImagesController{}, 102 | ), 103 | ), 104 | beego.NSNamespace("/echart", 105 | beego.NSInclude( 106 | &controllers.EchartController{}, 107 | ), 108 | ), 109 | beego.NSNamespace("/topology", 110 | beego.NSInclude( 111 | &controllers.TopologyController{}, 112 | ), 113 | ), 114 | beego.NSNamespace("/topodata", 115 | beego.NSInclude( 116 | &controllers.TopoDataController{}, 117 | ), 118 | ), 119 | beego.NSNamespace("/system", 120 | beego.NSInclude( 121 | &controllers.SystemController{}, 122 | ), 123 | ), 124 | beego.NSNamespace("/report", 125 | beego.NSInclude( 126 | &controllers.ReportController{}, 127 | ), 128 | ), 129 | beego.NSNamespace("/task_log", 130 | beego.NSInclude( 131 | &controllers.TaskLogController{}, 132 | ), 133 | ), 134 | beego.NSNamespace("/event_log", 135 | beego.NSInclude( 136 | &controllers.EventLogController{}, 137 | ), 138 | ), 139 | beego.NSNamespace("/rule", 140 | beego.NSInclude( 141 | &controllers.RuleController{}), 142 | ), 143 | beego.NSNamespace("/user", 144 | beego.NSInclude( 145 | &controllers.UserController{}), 146 | ), 147 | beego.NSNamespace("/group", 148 | beego.NSInclude( 149 | &controllers.GroupControllers{}), 150 | ), 151 | beego.NSNamespace("/ai", 152 | beego.NSInclude( 153 | &controllers.AIController{}), 154 | ), 155 | ) 156 | beego.AddNamespace(ns) 157 | } 158 | -------------------------------------------------------------------------------- /template/wechat_problem.tpl: -------------------------------------------------------------------------------- 1 | [{{.Status}}][{{.OccurTime.Format "15:04:05"}}]设备:{{.Hostname}}发生:{{.Message}}故障! 2 | ========================================= 3 | 告警主机: {{.Hostname}} 4 | 主机IP:{{.HostsIP}} 5 | 主机分组: {{.Hgroup}} 6 | 告警时间: {{.OccurTime.Format "2006-01-02 15:04:05"}} 7 | 告警等级: {{.Level}} 8 | 告警信息: {{.ItemName}} 9 | 告警项目: {{.Hkey}} 10 | 问题详情: {{.Detail}} 11 | 当前状态: {{.Status}} 12 | 事件ID: {{.EventID}} -------------------------------------------------------------------------------- /template/wechat_recovery.tpl: -------------------------------------------------------------------------------- 1 | [{{.Status}}][{{.OccurTime.Format "15:04:05"}}]设备:{{.Hostname}}发生:{{.Message}}已恢复! 2 | ========================================= 3 | 告警主机: {{.Hostname}} 4 | 主机IP:{{.HostsIP}} 5 | 主机分组: {{.Hgroup}} 6 | 告警时间: {{.OccurTime.Format "2006-01-02 15:04:05"}} 7 | 告警等级: {{.Level}} 8 | 告警信息: {{.ItemName}} 9 | 告警项目: {{.Hkey}} 10 | 问题详情: {{.Detail}} 11 | 持续时长:{{.EventDuration}} 12 | 当前状态: {{.Status}} 13 | 事件ID: {{.EventID}} -------------------------------------------------------------------------------- /zbxtable.init: -------------------------------------------------------------------------------- 1 | #!/bin/env bash 2 | # chkconfig: - 86 14 3 | # description: zbxtable daemon 4 | # 5 | 6 | ### BEGIN INIT INFO 7 | # Provides: zbxtable 8 | # Required-Start: $local_fs $network 9 | # Required-Stop: $local_fs $network 10 | # Default-Start: 11 | # Default-Stop: 0 1 2 3 4 5 6 12 | # Short-Description: Start and stop zbxtable 13 | # Description: zbxtable 14 | ### END INIT INFO 15 | 16 | # Source function library. 17 | . /etc/init.d/functions 18 | 19 | # ENV 20 | ZBXTABLE_HOME="/usr/local/zbxtable" 21 | APP_NAME="zbxtable" 22 | timeout=10 23 | lockfile=/var/lock/subsys/zbxtable 24 | 25 | start() 26 | { 27 | echo -n $"Starting ZbxTable: " 28 | cd $ZBXTABLE_HOME 29 | nohup $ZBXTABLE_HOME/$APP_NAME web >> $ZBXTABLE_HOME/logs/$APP_NAME.log 2>&1 & echo $! >/tmp/$APP_NAME.pid & 30 | rv=$? 31 | echo 32 | [ $rv -eq 0 ] && touch $lockfile 33 | return $rv 34 | } 35 | 36 | stop() 37 | { 38 | echo -n $"Shutting down ZbxTable: " 39 | killproc -p /tmp/$APP_NAME.pid -d $timeout 40 | rv=$? 41 | echo 42 | [ $rv -eq 0 ] && rm -f $lockfile 43 | return $rv 44 | } 45 | 46 | restart() 47 | { 48 | stop 49 | start 50 | } 51 | 52 | case "$1" in 53 | start|stop|restart) 54 | $1 55 | ;; 56 | force-reload) 57 | restart 58 | ;; 59 | *) 60 | echo $"Usage: $0 {start|stop|restart|force-reload}" 61 | exit 2 62 | ;; 63 | esac -------------------------------------------------------------------------------- /zbxtable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/canghai908/zbxtable/02ce3fa558241ad9a857254e5655e49278b12fd0/zbxtable.png -------------------------------------------------------------------------------- /zbxtable.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=zbxtable 3 | After=syslog.target 4 | After=network.target 5 | 6 | [Service] 7 | PIDFile=/tmp/zbxtable.pid 8 | User=zbxtable 9 | Group=zbxtable 10 | WorkingDirectory=/usr/local/zbxtable 11 | ExecStart=/bin/bash -c '/usr/local/zbxtable/zbxtable web' 12 | 13 | [Install] 14 | WantedBy=multi-user.target --------------------------------------------------------------------------------