1
- // Prometheus exporter for Open Nebula .
1
+ // Prometheus exporter for OpenNebula .
2
2
package main
3
3
4
4
import (
5
-
6
5
"net/http"
7
6
"os"
8
7
"path"
9
8
"strconv"
9
+ "strings"
10
10
"time"
11
11
12
12
"github.com/go-kit/kit/log"
13
13
"github.com/go-kit/kit/log/level"
14
14
15
15
"github.com/OpenNebula/one/src/oca/go/src/goca"
16
- "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/host"
17
16
18
17
"github.com/prometheus/client_golang/prometheus"
19
18
"github.com/prometheus/client_golang/prometheus/promauto"
@@ -24,39 +23,59 @@ import (
24
23
"gopkg.in/alecthomas/kingpin.v2"
25
24
)
26
25
27
- var (
26
+ type config struct {
27
+ user string
28
+ password string
29
+ endpoint string
30
+ interval int
31
+ host string
32
+ port int
33
+ path string
34
+ }
28
35
36
+ var (
29
37
poolTotalMemGauge = promauto .NewGauge (prometheus.GaugeOpts {
30
38
Name : "one_pool_totalmem" ,
31
- Help : "total memory of all hosts in open nebula " ,
39
+ Help : "total memory of all hosts in opennebula " ,
32
40
})
33
41
poolUsedMemGauge = promauto .NewGauge (prometheus.GaugeOpts {
34
42
Name : "one_pool_usedmem" ,
35
- Help : "used memory in all hosts in open nebula " ,
43
+ Help : "used memory in all hosts in opennebula " ,
36
44
})
37
45
poolTotalCPUGauge = promauto .NewGauge (prometheus.GaugeOpts {
38
46
Name : "one_pool_totalcpu" ,
39
- Help : "total cpu of all hosts in open nebula " ,
47
+ Help : "total cpu of all hosts in opennebula " ,
40
48
})
41
49
poolUsedCPUGauge = promauto .NewGauge (prometheus.GaugeOpts {
42
50
Name : "one_pool_usedcpu" ,
43
- Help : "used cpu in all hosts in open nebula " ,
51
+ Help : "used cpu in all hosts in opennebula " ,
44
52
})
45
53
poolActiveHostsGauge = promauto .NewGauge (prometheus.GaugeOpts {
46
54
Name : "one_pool_activehosts" ,
47
- Help : "number of active hosts in open nebula " ,
55
+ Help : "number of active hosts in opennebula " ,
48
56
})
49
57
poolRunningVMsGauge = promauto .NewGauge (prometheus.GaugeOpts {
50
58
Name : "one_pool_runningvms" ,
51
- Help : "number of running virtual machines in open nebula " ,
59
+ Help : "number of running virtual machines in opennebula " ,
52
60
})
53
61
)
54
62
55
- func recordMetrics (pool * host.Pool , logger log.Logger ) {
63
+ // recordMetrics from OpenNebula
64
+ func recordMetrics (config config , logger log.Logger ) {
56
65
57
- level .Info (logger ).Log ("msg" , "recording metrics from open nebula frontend" )
66
+ level .Info (logger ).Log ("msg" , "recording metrics from opennebula frontend" , "interval" , config .interval )
67
+
68
+ client := goca .NewDefaultClient (goca .NewConfig (config .user , config .password , config .endpoint ))
69
+ controller := goca .NewController (client )
58
70
59
71
for {
72
+
73
+ pool , err := controller .Hosts ().Info ()
74
+ if err != nil {
75
+ level .Error (logger ).Log ("msg" , "error retrieving hosts info" , "error" , err )
76
+ panic (err )
77
+ }
78
+
60
79
var totalMem int = 0
61
80
var usedMem int = 0
62
81
var totalCPU int = 0
@@ -67,7 +86,13 @@ func recordMetrics(pool *host.Pool, logger log.Logger) {
67
86
68
87
for _ , host := range pool .Hosts {
69
88
70
- level .Debug (logger ).Log ("msg" , "host metrics" , "host" , host .Name )
89
+ level .Debug (logger ).Log ("msg" , "host metrics" ,
90
+ "host" , host .Name ,
91
+ "TotalMem" , host .Share .TotalMem ,
92
+ "UsedMem" , host .Share .UsedMem ,
93
+ "TotalCPU" , host .Share .TotalCPU ,
94
+ "UsedCPU" , host .Share .UsedCPU ,
95
+ "RunningVMs" , host .Share .RunningVMs )
71
96
72
97
totalMem = totalMem + host .Share .TotalMem
73
98
usedMem = usedMem + host .Share .UsedMem
@@ -88,65 +113,78 @@ func recordMetrics(pool *host.Pool, logger log.Logger) {
88
113
89
114
poolActiveHostsGauge .Set (float64 (activeHosts ))
90
115
91
- time .Sleep (30 * time .Second )
116
+ time .Sleep (time . Duration ( config . interval ) * time .Second )
92
117
}
93
118
}
94
119
95
- func main () {
120
+ func newConfig ( fileName string , logger log. Logger ) config {
96
121
97
- var (
98
- user string
99
- password string
100
- host string
101
- port string
102
- )
122
+ viper .SetDefault ("endpoint" , "" ) // "" will be set to "http://localhost:2633/RPC2" by goca
123
+ viper .SetDefault ("interval" , 60 )
124
+ viper .SetDefault ("path" , "/metrics" )
125
+ viper .SetDefault ("port" , 9615 )
103
126
104
- logger := log .NewLogfmtLogger (log .NewSyncWriter (os .Stderr ))
105
- logger = log .With (logger , "ts" , log .DefaultTimestampUTC , "caller" , log .DefaultCaller )
106
-
107
- level .Info (logger ).Log ("msg" , "starting exporter for Open Nebula" )
108
-
109
- config := kingpin .Flag ("config" , "config file for one_exporter" ).Short ('c' ).String ()
110
- kingpin .Parse ()
111
127
112
128
viper .SetConfigType ("yaml" )
113
129
viper .AddConfigPath ("." )
114
130
115
- if * config != "" {
116
- level .Info (logger ).Log ("msg" , "using provided configuration file" , "config " , * config )
131
+ if fileName != "" {
132
+ level .Info (logger ).Log ("msg" , "using provided configuration file" , "file " , fileName )
117
133
118
- dir , file := path .Split (* config )
134
+ dir , file := path .Split (fileName )
119
135
viper .SetConfigName (file )
120
136
viper .AddConfigPath (dir )
121
137
}
122
138
123
139
err := viper .ReadInConfig ()
124
140
if err != nil {
125
141
level .Error (logger ).Log ("msg" , "error reading config file" , "error" , err )
126
- return
142
+ panic ( err )
127
143
}
128
144
129
- user = viper .Get ("user" ).(string )
130
- password = viper .Get ("password" ).(string )
131
- host = viper .Get ("host" ).(string )
132
- port = strconv .Itoa (viper .Get ("port" ).(int ))
145
+ return config {
146
+ user : viper .Get ("user" ).(string ),
147
+ password : viper .Get ("password" ).(string ),
148
+ endpoint : "" ,
149
+ interval : viper .Get ("interval" ).(int ),
150
+ host : viper .Get ("host" ).(string ),
151
+ port : viper .Get ("port" ).(int ),
152
+ path : viper .Get ("path" ).(string ),
153
+ }
133
154
134
- level . Info ( logger ). Log ( "msg" , "using config:" , "user" , user , "host" , host , "port" , port )
155
+ }
135
156
136
- conf := goca .NewConfig ( user , password , "" )
137
- client := goca .NewDefaultClient (conf )
138
- controller := goca .NewController (client )
157
+ func allowedLevel (logLevel string ) level.Option {
139
158
140
- pool , err := controller .Hosts ().Info ()
141
- if err != nil {
142
- level .Error (logger ).Log ("msg" , "error retrieving hosts info" , "error" , err )
143
- return
159
+ switch strings .ToLower (logLevel ) {
160
+ case "error" :
161
+ return level .AllowError ()
162
+ case "debug" :
163
+ return level .AllowDebug ()
164
+ default :
165
+ return level .AllowInfo ()
144
166
}
167
+ }
168
+
169
+ func main () {
170
+
171
+ logger := log .NewLogfmtLogger (log .NewSyncWriter (os .Stderr ))
172
+ logger = log .With (logger , "ts" , log .DefaultTimestampUTC , "caller" , log .DefaultCaller )
173
+
174
+ cfgFile := kingpin .Flag ("config" , "config file for one_exporter" ).Short ('c' ).String ()
175
+ logLevel := kingpin .Flag ("loglevel" , "the log level to output. options are error, info or debug. defaults to info" ).Short ('l' ).Default ("info" ).String ()
176
+ kingpin .Parse ()
177
+
178
+ logger = level .NewFilter (logger , allowedLevel (* logLevel ))
179
+ level .Info (logger ).Log ("msg" , "starting exporter for OpenNebula" )
180
+
181
+ config := newConfig (* cfgFile , logger )
182
+ level .Debug (logger ).Log ("msg" , "loaded config" , "user" , config .user , "endpoint" , config .endpoint )
145
183
146
- go recordMetrics (pool , logger )
184
+ go recordMetrics (config , logger )
147
185
148
- level .Info (logger ).Log ("msg" , "starting exporter on endpoint /metrics" )
149
- http .Handle ("/metrics" , promhttp .Handler ())
150
- http .ListenAndServe (host + ":" + port , nil )
186
+ level .Info (logger ).Log ("msg" , "starting exporter" , "host" , config . host , "port" , config . port , "path" , config . path )
187
+ http .Handle (config . path , promhttp .Handler ())
188
+ http .ListenAndServe (config . host + ":" + strconv . Itoa ( config . port ) , nil )
151
189
152
190
}
0 commit comments