├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── cmd └── root.go ├── go.mod ├── go.sum ├── main.go ├── oci8.pc ├── orametrics ├── ora.go ├── queries.go └── send.go ├── orazabbix.sh └── templates └── template.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea/workspace.xml 3 | .idea/tasks.xml 4 | .idea/gradle.xml 5 | .idea/dictionaries 6 | .idea/libraries 7 | .idea/ 8 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM oracle/instantclient:19 2 | 3 | RUN yum install -y gzip tar git wget gcc libstdc++.x86_64 compat-libstdc++-33.x86_64 gcc-c++.x86_64 4 | RUN wget https://dl.google.com/go/go1.13.7.linux-amd64.tar.gz 5 | RUN mkdir -p /usr/local/go && tar xzf go1.13.7.linux-amd64.tar.gz -C /usr/local/ 6 | ADD . /root/go/src/orazabbix/ 7 | WORKDIR /root/go/src/orazabbix/ 8 | ADD oci8.pc /usr/lib/oracle/19.5/client64/lib/ 9 | RUN PATH=$PATH:/usr/local/go/bin && \ 10 | export LD_LIBRARY_PATH=/usr/lib/oracle/19.5/client64/lib/ && \ 11 | export PKG_CONFIG_PATH=/usr/lib/oracle/19.5/client64/lib/ && \ 12 | export CGO_CFLAGS="-I/usr/include/oracle/19.5/client64/" && \ 13 | export CGO_LDFLAGS="-L/usr/lib/oracle/19.5/client64/lib/ -lstdc++ -lclntsh" && \ 14 | go mod vendor && go build -mod=vendor -tags noPkgConfig -o /orazabbix main.go 15 | ADD orazabbix.sh / 16 | 17 | CMD ["/orazabbix.sh"] 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [2017] [Farhad Farahi] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # orazabbix 2 | Oracle Database (Supporting RAC) Monitoring on Zabbix, Blazing Fast via Golang. 3 | 4 | ## Build Steps: 5 | 1. Clone repo 6 | 2. Setup oracle instant client and environment variables. [Guide](https://gocodecloud.com/blog/2016/08/09/accessing-an-oracle-db-in-go/) 7 | 3. `go build main.go` 8 | 9 | ``` 10 | Usage: 11 | orazabbix [flags] 12 | 13 | Flags: 14 | --alsologtostderr log to standard error as well as files 15 | -c, --connectionstring string ConnectionString to the Database, Format: username/password@ip:port/sid (default "system/oracle@localhost:1521/xe") 16 | -h, --help help for orazabbix 17 | -H, --host string Hostname of the monitored object in zabbix server (default "server1") 18 | --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) 19 | --log_dir string If non-empty, write log files in this directory 20 | --logtostderr log to standard error instead of files 21 | -p, --port int Zabbix Server/Proxy Port (default 10051) 22 | --stderrthreshold severity logs at or above this threshold go to stderr (default 2) 23 | -v, --v Level log level for V logs 24 | --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging 25 | -z, --zabbix string Zabbix Server/Proxy Hostname or IP address (default "localhost") 26 | ``` 27 | 28 | ## Installation: 29 | 1. Import template file in Zabbix server. 30 | 2. Add cron entry: 31 | 32 | ``` 33 | * * * * * oracle source /home/oracle/.bash_profile;/home/oracle/main -c /@:/ -z -p -H 2>&1 >/dev/null 34 | ``` 35 | 3. Restart cron service 36 | 4. Latest data in Zabbix frontend should start populating after a minute. 37 | 38 | ## Docker 39 | 1. Build instantclient image of choice, ie. 19.5 using oracle official [Dockerfile](https://github.com/oracle/docker-images/tree/master/OracleInstantClient). 40 | 2. Use provided Dockerfile to build the image and monitor remotely. 41 | 3. ```docker run -d --name orazabix /orazabbix.sh ``` 42 | 43 | ## Features: 44 | - Autodiscovery for tablespaces 45 | - Autodiscovery for ASM Diskgroups 46 | - Autodiscovery for Instances 47 | - Tablespace size (bytes/percent) 48 | - ASM Diskgroups size (bytes) 49 | - ASM Diskgroups Offline Disks Count 50 | - Alive 51 | - Archivelog switch 52 | - Blocking Sessions 53 | - Blocking Sessions Full Information 54 | - DB Block Changes 55 | - DB Block Gets 56 | - DB Consistent Gets 57 | - DB Files Size 58 | - DB Hit Ratio 59 | - DB Physical Reads 60 | - DB Version 61 | - Hit ratio - BODY 62 | - Hit ratio - SQLAREA 63 | - Hit ratio - TABLE/PROCEDURE 64 | - Hit ratio - TRIGGER 65 | - Max Processes 66 | - Max Sessions 67 | - Miss Latch 68 | - PGA 69 | - PGA Aggregate target 70 | - PHI/O Datafile Reads 71 | - PHI/O Datafile Writes 72 | - PHI/O Redo Writes 73 | - Pin hit ratio - BODY 74 | - Pin hit ratio - SQLAREA 75 | - Pin hit ratio - TABLE-PROCEDURE 76 | - Pin hit ratio - TRIGGER 77 | - Pool dict cache 78 | - Pool free mem 79 | - Pool lib cache 80 | - Pool misc 81 | - Pool sql area 82 | - Processes 83 | - Session Active 84 | - Session Inactive 85 | - Sessions 86 | - Session System 87 | - SGA buffer cache 88 | - SGA fixed 89 | - SGA java pool 90 | - SGA large pool 91 | - SGA log buffer 92 | - SGA shared pool 93 | - Uptime 94 | - Waits Controlfile I/O 95 | - Waits direct path read 96 | - Waits File I/O 97 | - Waits Logsync 98 | - Waits Logwrite 99 | - Waits multiblock read 100 | - Waits single block read 101 | - Waits SQLNet 102 | - Inst ID 103 | - Instance Number 104 | - Instance Name 105 | - Instance Hostname 106 | - Instance Version 107 | - Instance Startup Time 108 | - Instance Status 109 | - Instance Parallel 110 | - Instance Thread No 111 | - Instance Archiver 112 | - Instance Log Switch Wait 113 | - Instance Logins 114 | - Instance Pending Shutdown 115 | - Instance Database Status 116 | - Instance Role 117 | - Instance Active State 118 | - Instance Blocked 119 | - Instance Con ID 120 | - Instance Mode 121 | - Instance Edition 122 | - Instance Family 123 | - Instance Database Type -------------------------------------------------------------------------------- /cmd/root.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 Farhad Farahi 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package cmd 15 | 16 | import ( 17 | goflag "flag" 18 | "fmt" 19 | "github.com/mitchellh/go-homedir" 20 | "github.com/spf13/cobra" 21 | "github.com/spf13/viper" 22 | "log" 23 | "orazabbix/orametrics" 24 | "os" 25 | "strings" 26 | ) 27 | 28 | var ( 29 | cfgFile string 30 | connectionString string 31 | zabbixHost string 32 | zabbixPort int 33 | hostName string 34 | ) 35 | 36 | // RootCmd represents the base command when called without any subcommands 37 | var RootCmd = &cobra.Command{ 38 | Use: "orazabbix", 39 | Short: "Oracle database monitoring on Zabbix", 40 | Long: `Golang implementation of Oracle database monitoring on Zabbix`, 41 | // Uncomment the following line if your bare application 42 | // has an action associated with it: 43 | Run: runCmd, 44 | } 45 | 46 | func runCmd(cmd *cobra.Command, args []string) { 47 | goflag.CommandLine.Parse([]string{}) 48 | //if versionFlag := getFlagBoolPtr(cmd, "version"); versionFlag != nil { 49 | // fmt.Println("OraZabbix v1.0.0") 50 | //} else { 51 | orametrics.Init(connectionString, zabbixHost, zabbixPort, hostName) 52 | //} 53 | } 54 | 55 | // Execute adds all child commands to the root command sets flags appropriately. 56 | // This is called by main.main(). It only needs to happen once to the rootCmd. 57 | func Execute() { 58 | if err := RootCmd.Execute(); err != nil { 59 | fmt.Println(err) 60 | os.Exit(1) 61 | } 62 | } 63 | 64 | func init() { 65 | cobra.OnInitialize() 66 | 67 | // Here you will define your flags and configuration settings. 68 | // Cobra supports persistent flags, which, if defined here, 69 | // will be global for your application. 70 | //RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.orazabbix.yaml)") 71 | 72 | // Cobra also supports local flags, which will only run 73 | // when this action is called directly. 74 | //RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") 75 | //RootCmd.Flags().BoolP("version", "v", false, "Prints version information") 76 | RootCmd.Flags().StringVarP(&connectionString, "connectionstring", "c", "system/oracle@localhost:1521/xe", "ConnectionString to the Database, Format: username/password@ip:port/sid") 77 | RootCmd.Flags().StringVarP(&zabbixHost, "zabbix", "z", "localhost", "Zabbix Server/Proxy Hostname or IP address") 78 | RootCmd.Flags().IntVarP(&zabbixPort, "port", "p", 10051, "Zabbix Server/Proxy Port") 79 | RootCmd.Flags().StringVarP(&hostName, "host", "H", "server1", "Hostname of the monitored object in zabbix server") 80 | RootCmd.PersistentFlags().AddGoFlagSet(goflag.CommandLine) 81 | } 82 | 83 | func getFlagBoolPtr(cmd *cobra.Command, flag string) *bool { 84 | f := cmd.Flags().Lookup(flag) 85 | if f == nil { 86 | log.Printf("Flag accessed but not defined for command %s: %s", cmd.Name(), flag) 87 | } 88 | // Check if flag was not set at all. 89 | if !f.Changed && f.DefValue == f.Value.String() { 90 | return nil 91 | } 92 | var ret bool 93 | // Caseless compare. 94 | if strings.ToLower(f.Value.String()) == "true" { 95 | ret = true 96 | } else { 97 | ret = false 98 | } 99 | return &ret 100 | } 101 | 102 | // initConfig reads in config file and ENV variables if set. 103 | func initConfig() { 104 | if cfgFile != "" { 105 | // Use config file from the flag. 106 | viper.SetConfigFile(cfgFile) 107 | } else { 108 | // Find home directory. 109 | home, err := homedir.Dir() 110 | if err != nil { 111 | fmt.Println(err) 112 | os.Exit(1) 113 | } 114 | 115 | // Search config in home directory with name ".orazabbix" (without extension). 116 | viper.AddConfigPath(home) 117 | viper.SetConfigName(".orazabbix") 118 | } 119 | 120 | viper.AutomaticEnv() // read in environment variables that match 121 | 122 | // If a config file is found, read it in. 123 | if err := viper.ReadInConfig(); err == nil { 124 | fmt.Println("Using config file:", viper.ConfigFileUsed()) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module orazabbix 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/blacked/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc 7 | github.com/mattn/go-oci8 v0.0.3 8 | github.com/mitchellh/go-homedir v1.1.0 9 | github.com/rs/zerolog v1.17.2 10 | github.com/spf13/cobra v0.0.5 11 | github.com/spf13/viper v1.6.2 12 | ) 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 5 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 6 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 7 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 8 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 9 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 10 | github.com/blacked/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc h1:Ati6LK4Cd96ZjshZWdVSNq8e8E13krbSMskWJHfXpB4= 11 | github.com/blacked/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc/go.mod h1:MQFa+aV+n8IIKW8TvMLPCoq/HemkprtE8qU+pf8wXNo= 12 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 13 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 14 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 15 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 16 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 17 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 18 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 19 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 20 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 21 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 22 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 24 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 25 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= 26 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 27 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 28 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 29 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 30 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 31 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 32 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 33 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 34 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 35 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 36 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 37 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 38 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 39 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 40 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 41 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= 42 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 43 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 44 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 45 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 46 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 47 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 48 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 49 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 50 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 51 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 52 | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= 53 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 54 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 55 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 56 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 57 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 58 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 59 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 60 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 61 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 62 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 63 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 64 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 65 | github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= 66 | github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 67 | github.com/mattn/go-oci8 v0.0.3 h1:F3THEInvrjP0Rj7jTjFXvWmq1/95JPr+HZmQGSKjh1w= 68 | github.com/mattn/go-oci8 v0.0.3/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= 69 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 70 | github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 71 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 72 | github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= 73 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 74 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 75 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 76 | github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= 77 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 78 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 79 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 80 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 81 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 82 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 83 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 84 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 85 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 86 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 87 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 88 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 89 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 90 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 91 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 92 | github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= 93 | github.com/rs/zerolog v1.17.2 h1:RMRHFw2+wF7LO0QqtELQwo8hqSmqISyCJeFeAAuWcRo= 94 | github.com/rs/zerolog v1.17.2/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I= 95 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 96 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 97 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= 98 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 99 | github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= 100 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 101 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 102 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 103 | github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= 104 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 105 | github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= 106 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 107 | github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= 108 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 109 | github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= 110 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 111 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 112 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 113 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 114 | github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= 115 | github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= 116 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 117 | github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= 118 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 119 | github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= 120 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 121 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 122 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 123 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 124 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 125 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 126 | github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= 127 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 128 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 129 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 130 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 131 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 132 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 133 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 134 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 135 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 136 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 137 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 138 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 139 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 140 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 141 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 142 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 143 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 144 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 145 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 146 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 147 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 148 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 149 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 150 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 151 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 152 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= 153 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 154 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 155 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 156 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 157 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 158 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 159 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 160 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 161 | golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 162 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 163 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 164 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 165 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 166 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 167 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 168 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 169 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 170 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 171 | gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= 172 | gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 173 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 174 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 175 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 176 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 177 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 178 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 179 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 180 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright © 2017 Farhad Farahi 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package main 15 | 16 | import ( 17 | "orazabbix/cmd" 18 | ) 19 | 20 | func main() { 21 | cmd.Execute() 22 | } 23 | -------------------------------------------------------------------------------- /oci8.pc: -------------------------------------------------------------------------------- 1 | prefix=/usr/lib/oracle/19.5/client64 2 | exec_prefix=${prefix} 3 | libdir=${exec_prefix} 4 | includedir=/usr/include/oracle/19.5/client64/ 5 | 6 | glib_genmarshal=glib-genmarshal 7 | gobject_query=gobject-query 8 | glib_mkenums=glib-mkenums 9 | 10 | Name: oci8 11 | Description: oci8 library 12 | Libs: -L${libdir} -lclntsh 13 | Cflags: -I${includedir} 14 | Version: 19.5 -------------------------------------------------------------------------------- /orametrics/ora.go: -------------------------------------------------------------------------------- 1 | package orametrics 2 | 3 | import ( 4 | "database/sql" 5 | _ "github.com/mattn/go-oci8" 6 | "github.com/rs/zerolog/log" 7 | "strconv" 8 | "time" 9 | ) 10 | 11 | type tsBytes struct { 12 | Ts string `json:"TS"` 13 | Bytes string `json:"bytes"` 14 | } 15 | 16 | type diskgroups struct { 17 | Dg string `json:"DG"` 18 | UsableFileMB string `json:"USABLE_FILE_MB"` 19 | OfflineDisks string `json:"OFFLINE_DISKS"` 20 | } 21 | 22 | type instance struct { 23 | INST_ID string `json:"INST_ID"` 24 | INSTANCE_NUMBER string `json:"INSTANCE_NUMBER"` 25 | INSTANCE_NAME string `json:"INSTANCE_NAME"` 26 | HOST_NAME string `json:"HOST_NAME"` 27 | VERSION string `json:"VERSION"` 28 | STARTUP_TIME string `json:"STARTUP_TIME"` 29 | STATUS string `json:"STATUS"` 30 | PARALLEL string `json:"PARALLEL"` 31 | THREAD_NO string `json:"THREAD_NO"` 32 | ARCHIVER string `json:"ARCHIVER"` 33 | LOG_SWITCH_WAIT sql.NullString `json:"LOG_SWITCH_WAIT"` 34 | LOGINS string `json:"LOGINS"` 35 | SHUTDOWN_PENDING string `json:"SHUTDOWN_PENDING"` 36 | DATABASE_STATUS string `json:"DATABASE_STATUS"` 37 | INSTANCE_ROLE string `json:"INSTANCE_ROLE"` 38 | ACTIVE_STATE string `json:"ACTIVE_STATE"` 39 | BLOCKED string `json:"BLOCKED"` 40 | CON_ID string `json:"CON_ID"` 41 | INSTANCE_MODE string `json:"INSTANCE_MODE"` 42 | EDITION string `json:"EDITION"` 43 | FAMILY sql.NullString `json:"FAMILY"` 44 | DATABASE_TYPE string `json:"DATABASE_TYPE"` 45 | } 46 | 47 | func Init(connectionString string, zabbixHost string, zabbixPort int, hostName string) { 48 | start := time.Now() 49 | 50 | defer log.Info().Dur("took", time.Since(start)).Msg("") 51 | db, err := sql.Open("oci8", connectionString) 52 | if err != nil { 53 | log.Error().Err(err).Msg("Connection Failed!") 54 | return 55 | } 56 | defer db.Close() 57 | 58 | if err = db.Ping(); err != nil { 59 | log.Error().Err(err).Msg("Error connecting to the database") 60 | return 61 | } 62 | zabbixData := make(map[string]string) 63 | for k, v := range queries { 64 | rows, err := db.Query(v) 65 | if err != nil { 66 | log.Error().Err(err).Msg("Error fetching") 67 | return 68 | } 69 | defer rows.Close() 70 | 71 | for rows.Next() { 72 | var res string 73 | err := rows.Scan(&res) 74 | if err != nil { 75 | 76 | } 77 | zabbixData[k] = res 78 | } 79 | } 80 | if zabbixData["pool_dict_cache"] == "" { 81 | zabbixData["pool_dict_cache"] = "0" 82 | } 83 | if zabbixData["pool_lib_cache"] == "" { 84 | zabbixData["pool_lib_cache"] = "0" 85 | } 86 | if zabbixData["pool_sql_area"] == "" { 87 | zabbixData["pool_sql_area"] = "0" 88 | } 89 | discoveryData := make(map[string]string) 90 | for k, v := range discoveryQueries { 91 | if k == "tablespaces" { 92 | result := runDiscoveryQuery(v, db) 93 | fix := "{\"data\":[" 94 | count := 1 95 | for _, va := range result { 96 | if count < len(result) { 97 | fix = fix + "{\"{#TS}\":\"" + va + "\"}," 98 | } else { 99 | fix = fix + "{\"{#TS}\":\"" + va + "\"}" 100 | } 101 | count++ 102 | } 103 | fix = fix + "]}" 104 | discoveryData[k] = fix 105 | } 106 | if k == "diskgroups" { 107 | resultd := runDiscoveryQuery(v, db) 108 | var fixd = "{\"data\":[" 109 | countd := 1 110 | lend := len(resultd) 111 | for _, vd := range resultd { 112 | if countd < lend { 113 | fixd = fixd + "{\"{#DG}\":\"" + vd + "\"}," 114 | } else { 115 | fixd = fixd + "{\"{#DG}\":\"" + vd + "\"}" 116 | } 117 | countd++ 118 | } 119 | fixd = fixd + "]}" 120 | discoveryData[k] = fixd 121 | } 122 | if k == "instances" { 123 | resultI := runDiscoveryQuery(v, db) 124 | var fixd string = "{\"data\":[" 125 | countI := 1 126 | lend := len(resultI) 127 | for _, vi := range resultI { 128 | if countI < lend { 129 | fixd = fixd + "{\"{#INS}\":\"" + vi + "\"}," 130 | } else { 131 | fixd = fixd + "{\"{#INS}\":\"" + vi + "\"}" 132 | } 133 | countI++ 134 | } 135 | fixd = fixd + "]}" 136 | discoveryData[k] = fixd 137 | } 138 | } 139 | 140 | ts_usage_bytes := runTsBytesDiscoveryQuery(ts_usage_bytes, db) 141 | ts_usage_pct := runTsBytesDiscoveryQuery(ts_usage_pct, db) 142 | diskGroupsMetrics := runDiskGroupsMetrics(diskgroup_metrics, db) 143 | instanceMetrics := runInstanceMetrics(instance_metrics, db) 144 | discoveryMetrics := make(map[string]string) 145 | for _, v := range ts_usage_bytes { 146 | discoveryMetrics[`ts_usage_bytes[`+v.Ts+`]`] = v.Bytes 147 | } 148 | for _, v := range ts_usage_pct { 149 | discoveryMetrics[`ts_usage_pct[`+v.Ts+`]`] = v.Bytes 150 | } 151 | for _, v := range diskGroupsMetrics { 152 | bytes, _ := strconv.Atoi(v.UsableFileMB) 153 | bytes = bytes * 1048576 154 | bytesS := strconv.Itoa(bytes) 155 | discoveryMetrics[`usable_file_mb[`+v.Dg+`]`] = bytesS 156 | discoveryMetrics[`offline_disks[`+v.Dg+`]`] = v.OfflineDisks 157 | } 158 | for _, v := range instanceMetrics { 159 | discoveryMetrics[`INST_ID[`+v.INSTANCE_NAME+`]`] = v.INST_ID 160 | discoveryMetrics[`INSTANCE_NUMBER[`+v.INSTANCE_NAME+`]`] = v.INSTANCE_NUMBER 161 | discoveryMetrics[`HOST_NAME[`+v.INSTANCE_NAME+`]`] = v.HOST_NAME 162 | discoveryMetrics[`VERSION[`+v.INSTANCE_NAME+`]`] = v.VERSION 163 | discoveryMetrics[`STARTUP_TIME[`+v.INSTANCE_NAME+`]`] = v.STARTUP_TIME 164 | discoveryMetrics[`STATUS[`+v.INSTANCE_NAME+`]`] = v.STATUS 165 | discoveryMetrics[`PARALLEL[`+v.INSTANCE_NAME+`]`] = v.PARALLEL 166 | discoveryMetrics[`THREAD_NO[`+v.INSTANCE_NAME+`]`] = v.THREAD_NO 167 | discoveryMetrics[`ARCHIVER[`+v.INSTANCE_NAME+`]`] = v.ARCHIVER 168 | if v.LOG_SWITCH_WAIT.Valid == true { 169 | discoveryMetrics[`LOG_SWITCH_WAIT[`+v.INSTANCE_NAME+`]`] = v.LOG_SWITCH_WAIT.String 170 | } else { 171 | discoveryMetrics[`LOG_SWITCH_WAIT[`+v.INSTANCE_NAME+`]`] = "0" 172 | } 173 | discoveryMetrics[`LOGINS[`+v.INSTANCE_NAME+`]`] = v.LOGINS 174 | discoveryMetrics[`SHUTDOWN_PENDING[`+v.INSTANCE_NAME+`]`] = v.SHUTDOWN_PENDING 175 | discoveryMetrics[`DATABASE_STATUS[`+v.INSTANCE_NAME+`]`] = v.DATABASE_STATUS 176 | discoveryMetrics[`INSTANCE_ROLE[`+v.INSTANCE_NAME+`]`] = v.INSTANCE_ROLE 177 | discoveryMetrics[`ACTIVE_STATE[`+v.INSTANCE_NAME+`]`] = v.ACTIVE_STATE 178 | discoveryMetrics[`BLOCKED[`+v.INSTANCE_NAME+`]`] = v.BLOCKED 179 | discoveryMetrics[`CON_ID[`+v.INSTANCE_NAME+`]`] = v.CON_ID 180 | discoveryMetrics[`INSTANCE_MODE[`+v.INSTANCE_NAME+`]`] = v.INSTANCE_MODE 181 | discoveryMetrics[`EDITION[`+v.INSTANCE_NAME+`]`] = v.EDITION 182 | discoveryMetrics[`FAMILY[`+v.INSTANCE_NAME+`]`] = v.FAMILY.String 183 | discoveryMetrics[`DATABASE_TYPE[`+v.INSTANCE_NAME+`]`] = v.DATABASE_TYPE 184 | } 185 | for k, v := range discoveryMetrics { 186 | zabbixData[k] = v 187 | } 188 | for k, v := range discoveryData { 189 | zabbixData[k] = v 190 | } 191 | 192 | send(zabbixData, zabbixHost, zabbixPort, hostName) 193 | } 194 | func runDiscoveryQuery(query string, db *sql.DB) []string { 195 | rows, err := db.Query(query) 196 | if err != nil { 197 | log.Error().Err(err).Msg("Error fetching") 198 | return nil 199 | } 200 | defer rows.Close() 201 | var result []string 202 | for rows.Next() { 203 | var res string 204 | rows.Scan(&res) 205 | result = append(result, res) 206 | } 207 | return result 208 | } 209 | 210 | func runTsBytesDiscoveryQuery(query string, db *sql.DB) []tsBytes { 211 | rows, err := db.Query(query) 212 | if err != nil { 213 | log.Error().Err(err).Msg("Error fetching") 214 | return nil 215 | } 216 | defer rows.Close() 217 | var result []tsBytes 218 | for rows.Next() { 219 | var res tsBytes 220 | rows.Scan(&res.Ts, &res.Bytes) 221 | 222 | result = append(result, res) 223 | } 224 | return result 225 | } 226 | 227 | func runDiskGroupsMetrics(query string, db *sql.DB) []diskgroups { 228 | rows, err := db.Query(query) 229 | if err != nil { 230 | log.Error().Err(err).Msg("Error fetching") 231 | return nil 232 | } 233 | defer rows.Close() 234 | var result []diskgroups 235 | for rows.Next() { 236 | var res diskgroups 237 | rows.Scan(&res.Dg, &res.UsableFileMB, &res.OfflineDisks) 238 | result = append(result, res) 239 | } 240 | return result 241 | } 242 | 243 | func runInstanceMetrics(query string, db *sql.DB) []instance { 244 | rows, err := db.Query(query) 245 | if err != nil { 246 | log.Error().Err(err).Msg("Error fetching") 247 | return nil 248 | } 249 | defer rows.Close() 250 | var result []instance 251 | for rows.Next() { 252 | var res instance 253 | err := rows.Scan(&res.INST_ID, &res.INSTANCE_NUMBER, &res.INSTANCE_NAME, &res.HOST_NAME, &res.VERSION, &res.STARTUP_TIME, 254 | &res.STATUS, &res.PARALLEL, &res.THREAD_NO, &res.ARCHIVER, &res.LOG_SWITCH_WAIT, &res.LOGINS, 255 | &res.SHUTDOWN_PENDING, &res.DATABASE_STATUS, &res.INSTANCE_ROLE, &res.ACTIVE_STATE, &res.BLOCKED, &res.CON_ID, 256 | &res.INSTANCE_MODE, &res.EDITION, &res.FAMILY, &res.DATABASE_TYPE) 257 | result = append(result, res) 258 | if err != nil { 259 | log.Error().Err(err).Msg("") 260 | } 261 | 262 | } 263 | return result 264 | } 265 | -------------------------------------------------------------------------------- /orametrics/queries.go: -------------------------------------------------------------------------------- 1 | package orametrics 2 | 3 | var queries = map[string]string{ 4 | "alive": "select 1 from dual", 5 | "archivelog_switch": "select count(*) from gv$log_history where first_time >= (sysdate - 1 / 24)", 6 | "uptime": "select to_char ( (sysdate - startup_time) *24*60 , 'FM99999999999999990') from gv$instance", 7 | "dbblockgets": "select sum (value) from gv$sysstat where name = 'db block gets'", 8 | "dbblockchanges": "select sum (value) from gv$sysstat where name = 'db block changes'", 9 | "dbconsistentgets": "select sum (value) from gv$sysstat where name = 'consistent gets'", 10 | "dbphysicalreads": "select sum (value) from gv$sysstat where name = 'physical reads'", 11 | "dbhitratio": "select ( sum (case name when 'consistent gets' then value else 0 end) + sum (case name when 'db block gets' then value else 0 end) - sum (case name when 'physical reads' then value else 0 end)) / ( sum (case name when 'consistent gets' then value else 0 end) + sum (case name when 'db block gets' then value else 0 end)) * 100 from gv$sysstat", 12 | "hitratio_body": "select gethitratio * 100 from gv$librarycache where namespace = 'BODY'", 13 | "hitratio_sqlarea": "select gethitratio * 100 from gv$librarycache where namespace = 'SQL AREA'", 14 | "hitratio_trigger": "select gethitratio * 100 from gv$librarycache where namespace = 'TRIGGER'", 15 | "hitratio_table_proc": "select gethitratio * 100 from gv$librarycache where namespace = 'TABLE/PROCEDURE'", 16 | "miss_latch": "select sum (misses) from gv$latch", 17 | "pga_aggregate_target": "select value from gv$pgastat where name = 'aggregate PGA target parameter'", 18 | "pga": "select value from gv$pgastat where name = 'total PGA inuse'", 19 | "phio_datafile_reads": "select sum (value) from gv$sysstat where name = 'physical reads direct'", 20 | "phio_datafile_writes": "select sum (value) from gv$sysstat where name = 'physical writes direct'", 21 | "phio_redo_writes": "select sum (value) from gv$sysstat where name = 'redo writes'", 22 | "pinhitratio_body": "select pins / (pins + reloads) * 100 from gv$librarycache where namespace = 'BODY'", 23 | "pinhitratio_sqlarea": "select pins / (pins + reloads) * 100 from gv$librarycache where namespace = 'SQL AREA'", 24 | "pinhitratio_trigger": "select pins / (pins + reloads) * 100 from gv$librarycache where namespace = 'TRIGGER'", 25 | "pinhitratio_table_proc": "select pins / (pins + reloads) * 100 from gv$librarycache where namespace = 'TABLE/PROCEDURE'", 26 | //pool_dict_cache maybe empty, check and insert zero instead 27 | "pool_dict_cache": "select bytes from gv$sgastat where pool = 'shared pool' and name = 'dictionary cache'", 28 | "pool_free_mem": "select bytes from gv$sgastat where pool = 'shared pool' and name = 'free memory'", 29 | //pool_lib_cache maybe empty, check and insert zero instead 30 | "pool_lib_cache": "select bytes from gv$sgastat where pool = 'shared pool' and name = 'library cache'", 31 | //pool_sql_area maybe empty, check and insert zero instead 32 | "pool_sql_area": "select bytes from gv$sgastat where pool = 'shared pool' and name = 'sql area'", 33 | "pool_misc": "select sum (bytes) from gv$sgastat where pool = 'shared pool' and name not in ('library cache', 'dictionary cache', 'free memory', 'sql area')", 34 | "maxprocs": "select value from gv$parameter where name = 'processes'", 35 | "procnum": "select count (*) from gv$process", 36 | "maxsession": "select value from gv$parameter where name = 'sessions'", 37 | "session": "select count (*) from gv$session", 38 | "session_system": "select count (*) from gv$session where type = 'BACKGROUND'", 39 | "session_active": "select count (*) from gv$session where type != 'BACKGROUND' and status = 'ACTIVE'", 40 | "session_inactive": "select count (*) from gv$session where type != 'BACKGROUND' and status = 'INACTIVE'", 41 | "sga_buffer_cache": "select sum (bytes) from gv$sgastat where name in ('db_block_buffers', 'buffer_cache')", 42 | "sga_fixed": "select sum (bytes) from gv$sgastat where name = 'fixed_sga'", 43 | "sga_java_pool": "select sum (bytes) from gv$sgastat where pool = 'java pool'", 44 | "sga_large_pool": "select sum (bytes) from gv$sgastat where pool = 'large pool'", 45 | "sga_shared_pool": "select sum (bytes) from gv$sgastat where pool = 'shared pool'", 46 | "sga_log_buffer": "select sum (bytes) from gv$sgastat where name = 'log_buffer'", 47 | "waits_directpath_read": "select total_waits from gv$system_event where event = 'direct path read'", 48 | "waits_file_io": "select nvl (sum (total_waits), 0) from gv$system_event where event in ('file identify', 'file open')", 49 | "waits_controlfileio": "select sum (total_waits) from gv$system_event where event in ('control file sequential read' , 'control file single write' , 'control file parallel write')", 50 | "waits_logwrite": "select sum (total_waits) from gv$system_event where event in ('log file single write', 'log file parallel write')", 51 | "waits_logsync": "select sum(total_waits) from gv$system_event where event = 'log file sync'", 52 | "waits_multiblock_read": "select sum (total_waits) from gv$system_event where event = 'db file scattered read'", 53 | "waits_singleblock_read": "select sum (total_waits) from gv$system_event where event = 'db file sequential read'", 54 | //waits_sqlnet maybe empty, check and insert zero instead 55 | "waits_sqlnet": "select count(*) from (select rootid from (select level lvl , connect_by_root (inst_id || '.' || sid) rootid , seconds_in_wait from gv$session start with blocking_session is null connect by nocycle prior inst_id = blocking_instance and prior sid = blocking_session) where lvl > 1 group by rootid having sum(seconds_in_wait) > 300)", 56 | //blocking_sessions maybe empty, check and insert zero instead 57 | "blocking_sessions": `select count(*) from (select rootid from (select level lvl, connect_by_root (inst_id || '.' || sid) rootid, seconds_in_wait from gv$session start with blocking_session is null connect by nocycle prior inst_id = blocking_instance and prior sid = blocking_session) where lvl > 1 group by rootid having sum(seconds_in_wait) > 300)`, 58 | "blocking_sessions_full": `select lpad(' ', (level - 1) * 4) 59 | || 'INST_ID : ' 60 | || inst_id 61 | || chr(10) 62 | || lpad(' ', (level - 1) * 4) 63 | || 'SERVICE_NAME : ' 64 | || service_name 65 | || chr(10) 66 | || lpad(' ', (level - 1) * 4) 67 | || 'SID,SERIAL : ' 68 | || sid 69 | || ',' 70 | || serial# 71 | || chr(10) 72 | || lpad(' ', (level - 1) * 4) 73 | || 'USERNAME : ' 74 | || username 75 | || chr(10) 76 | || lpad(' ', (level - 1) * 4) 77 | || 'OSUSER : ' 78 | || osuser 79 | || chr(10) 80 | || lpad(' ', (level - 1) * 4) 81 | || 'MACHINE : ' 82 | || machine 83 | || chr(10) 84 | || lpad(' ', (level - 1) * 4) 85 | || 'PROGRAM : ' 86 | || program 87 | || chr(10) 88 | || lpad(' ', (level - 1) * 4) 89 | || 'MODULE : ' 90 | || module 91 | || chr(10) 92 | || lpad(' ', (level - 1) * 4) 93 | || 'SQL_ID : ' 94 | || sql_id 95 | || chr(10) 96 | || lpad(' ', (level - 1) * 4) 97 | || 'EVENT : ' 98 | || event 99 | || chr(10) 100 | || lpad(' ', (level - 1) * 4) 101 | || 'SECONDS_IN_WAIT : ' 102 | || seconds_in_wait 103 | || chr(10) 104 | || lpad(' ', (level - 1) * 4) 105 | || 'STATE : ' 106 | || state 107 | || chr(10) 108 | || lpad(' ', (level - 1) * 4) 109 | || 'STATUS : ' 110 | || status 111 | || chr(10) 112 | || lpad(' ', (level - 1) * 4) 113 | || '=========================' 114 | || chr(10) 115 | blocking_sess_info 116 | from ( 117 | select inst_id || '.' || sid id 118 | , case 119 | when blocking_instance is not null 120 | then 121 | blocking_instance || '.' || blocking_session 122 | end 123 | parent_id 124 | , inst_id 125 | , service_name 126 | , sid 127 | , serial# 128 | , username 129 | , osuser 130 | , machine 131 | , program 132 | , module 133 | , sql_id 134 | , event 135 | , seconds_in_wait 136 | , state 137 | , status 138 | , level lvl 139 | , connect_by_isleaf isleaf 140 | , connect_by_root (inst_id || '.' || sid) rootid 141 | from gv$session 142 | start with blocking_session is null 143 | connect by nocycle prior inst_id = blocking_instance 144 | and prior sid = blocking_session 145 | ) 146 | where lvl || isleaf <> '11' 147 | and rootid in 148 | ( 149 | select rootid 150 | from ( 151 | select level lvl 152 | , connect_by_root (inst_id || '.' || sid) rootid 153 | , seconds_in_wait 154 | from gv$session 155 | start with blocking_session is null 156 | connect by nocycle prior inst_id = blocking_instance 157 | and prior sid = blocking_session 158 | ) 159 | where lvl > 1 160 | group by rootid 161 | having sum(seconds_in_wait) > 300 162 | ) 163 | connect by nocycle prior id = parent_id 164 | start with parent_id is null`, 165 | "dbversion": "select banner from gv$version where banner like '%Oracle Database%'", 166 | } 167 | var discoveryQueries = map[string]string{ 168 | "tablespaces": "select name ts from gv$tablespace", 169 | "diskgroups" : "select name from v$asm_diskgroup", 170 | "instances" : "select instance_name from gv$instance", 171 | } 172 | 173 | var ( 174 | ts_usage_pct string = "select tablespace_name ts, round(used_percent, 5) pct from dba_tablespace_usage_metrics" 175 | ts_usage_bytes string = "select ta.tablespace_name as ts, ta.used_space * tb.block_size as bytes from dba_tablespace_usage_metrics ta join dba_tablespaces tb on ta.tablespace_name = tb.tablespace_name" 176 | diskgroup_metrics string = "select name as Dg,USABLE_FILE_MB as UsableFileMB, OFFLINE_DISKS as OfflineDisks from v$asm_diskgroup" 177 | instance_metrics string = "select INST_ID, INSTANCE_NUMBER, INSTANCE_NAME, HOST_NAME, VERSION, STARTUP_TIME, STATUS, PARALLEL, THREAD# AS THREAD_NO, ARCHIVER, LOG_SWITCH_WAIT, LOGINS, SHUTDOWN_PENDING, DATABASE_STATUS, INSTANCE_ROLE, ACTIVE_STATE, BLOCKED, CON_ID, INSTANCE_MODE, EDITION, FAMILY, DATABASE_TYPE from gv$instance" 178 | ) 179 | -------------------------------------------------------------------------------- /orametrics/send.go: -------------------------------------------------------------------------------- 1 | package orametrics 2 | 3 | import ( 4 | . "github.com/blacked/go-zabbix" 5 | "time" 6 | ) 7 | 8 | func send(zabbixData map[string]string, zabbixHost string, zabbixPort int, hostName string) { 9 | var metrics []*Metric 10 | for k, v := range zabbixData { 11 | metrics = append(metrics, NewMetric(hostName, k, v, time.Now().Unix())) 12 | //metrics = append(metrics, NewMetric("server1", "status", "OK")) 13 | } 14 | // Create instance of Packet class 15 | packet := NewPacket(metrics) 16 | 17 | // Send packet to zabbix 18 | z := NewSender(zabbixHost, zabbixPort) 19 | z.Send(packet) 20 | } 21 | -------------------------------------------------------------------------------- /orazabbix.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | while true 3 | do 4 | /orazabbix $@ 5 | sleep 30 6 | done 7 | --------------------------------------------------------------------------------