Skip to content
This repository was archived by the owner on Jan 21, 2025. It is now read-only.

Commit c20ddf9

Browse files
sbueringerchrischdi
authored andcommitted
add server metrics
1 parent f4a4613 commit c20ddf9

File tree

4 files changed

+103
-9
lines changed

4 files changed

+103
-9
lines changed

main.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ func updateMetrics(provider *gophercloud.ProviderClient, eo gophercloud.Endpoint
232232
var errs []error
233233
scrapeStart := time.Now()
234234

235-
cinderClient, neutronClient, loadbalancerClient, err := getClients(provider, eo)
235+
cinderClient, neutronClient, loadbalancerClient, computeClient, err := getClients(provider, eo)
236236
if err != nil {
237237
err := logError("creating openstack clients failed: %v", err)
238238
errs = append(errs, err)
@@ -252,6 +252,11 @@ func updateMetrics(provider *gophercloud.ProviderClient, eo gophercloud.Endpoint
252252
errs = append(errs, err)
253253
}
254254

255+
if err := metrics.PublishServerMetrics(computeClient, tenantID); err != nil {
256+
err := logError("scraping server metrics failed: %v", err)
257+
errs = append(errs, err)
258+
}
259+
255260
// check if Neutron is using FWaaS v1
256261
// if FWaaS v2 is enabled, the extension alias is fwaas_v2 (the directories are the extension names)
257262
// https://godoc.org/github.com/gophercloud/gophercloud/acceptance/openstack/networking/v2/extensions
@@ -292,27 +297,32 @@ func updateMetrics(provider *gophercloud.ProviderClient, eo gophercloud.Endpoint
292297
return nil
293298
}
294299

295-
func getClients(provider *gophercloud.ProviderClient, endpointOpts gophercloud.EndpointOpts) (cinder, neutron, loadbalancer *gophercloud.ServiceClient, err error) {
300+
func getClients(provider *gophercloud.ProviderClient, endpointOpts gophercloud.EndpointOpts) (cinder, neutron, loadbalancer, compute *gophercloud.ServiceClient, err error) {
296301
cinderClient, err := openstack.NewBlockStorageV2(provider, endpointOpts)
297302
if err != nil {
298-
return nil, nil, nil, fmt.Errorf("unable to get cinder client: %v", err)
303+
return nil, nil, nil, nil, fmt.Errorf("unable to get cinder client: %v", err)
299304
}
300305

301306
neutronClient, err := openstack.NewNetworkV2(provider, endpointOpts)
302307
if err != nil {
303-
return nil, nil, nil, fmt.Errorf("unable to get neutron client: %v", err)
308+
return nil, nil, nil, nil, fmt.Errorf("unable to get neutron client: %v", err)
309+
}
310+
311+
computeClient, err := openstack.NewComputeV2(provider, endpointOpts)
312+
if err != nil {
313+
return nil, nil, nil, nil, fmt.Errorf("unable to get compute client: %v", err)
304314
}
305315

306316
if _, err := provider.EndpointLocator(gophercloud.EndpointOpts{Type: "load-balancer", Availability: gophercloud.AvailabilityPublic}); err != nil {
307317
// we can use the neutron client to access lbaas because no octavia is available
308-
return cinderClient, neutronClient, neutronClient, nil
318+
return cinderClient, neutronClient, neutronClient, computeClient, nil
309319
}
310320

311321
loadbalancerClient, err := openstack.NewLoadBalancerV2(provider, endpointOpts)
312322
if err != nil {
313-
return nil, nil, nil, fmt.Errorf("failed to create loadbalancer service client: %v", err)
323+
return nil, nil, nil, nil, fmt.Errorf("failed to create loadbalancer service client: %v", err)
314324
}
315-
return cinderClient, neutronClient, loadbalancerClient, nil
325+
return cinderClient, neutronClient, loadbalancerClient, computeClient, nil
316326
}
317327

318328
func min(a, b time.Duration) time.Duration {

pkg/metrics/loadbalancer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func registerLoadBalancerMetrics() {
2323
loadbalancerAdminStateUp = prometheus.NewGaugeVec(
2424
prometheus.GaugeOpts{
2525
Name: generateName("loadbalancer_admin_state_up"),
26-
Help: "Load balancer status",
26+
Help: "Load balancer admin state up",
2727
},
2828
loadBalancerLabels,
2929
)
@@ -69,7 +69,7 @@ func PublishLoadBalancerMetrics(client *gophercloud.ServiceClient, tenantID stri
6969
return nil
7070
}
7171

72-
// publishLoadBalancerMetric extracts data from a floating ip and exposes the metrics via prometheus
72+
// publishLoadBalancerMetric extracts data from a load balancer and exposes the metrics via prometheus
7373
func publishLoadBalancerMetric(lb loadbalancers.LoadBalancer) {
7474
labels := []string{lb.ID, lb.VipAddress, lb.Provider, lb.VipPortID}
7575

pkg/metrics/metrics.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func RegisterMetrics(prefix string) {
2323
registerLoadBalancerMetrics()
2424
registerOpenStackMetrics()
2525
registerFWaaSV1Metrics()
26+
registerServerMetrics()
2627
}
2728

2829
// AddPrefix adds the given prefix to the string, if set

pkg/metrics/nova.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-License-Identifier: MIT
2+
3+
package metrics
4+
5+
import (
6+
"github.com/gophercloud/gophercloud"
7+
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
8+
"github.com/prometheus/client_golang/prometheus"
9+
"k8s.io/klog"
10+
)
11+
12+
var (
13+
serverStatus *prometheus.GaugeVec
14+
serverVolumeAttachmentCount *prometheus.GaugeVec
15+
16+
// possible server states, from https://github.com/openstack/nova/blob/master/nova/objects/fields.py#L949
17+
states = []string{"ACTIVE", "BUILDING", "PAUSED", "SUSPENDED", "STOPPED", "RESCUED", "RESIZED", "SOFT_DELETED", "DELETED", "ERROR", "SHELVED", "SHELVED_OFFLOADED"}
18+
19+
serverLabels = []string{"id"}
20+
)
21+
22+
func registerServerMetrics() {
23+
serverStatus = prometheus.NewGaugeVec(
24+
prometheus.GaugeOpts{
25+
Name: generateName("server_status"),
26+
Help: "Server status",
27+
},
28+
append(serverLabels, "status"),
29+
)
30+
serverVolumeAttachmentCount = prometheus.NewGaugeVec(
31+
prometheus.GaugeOpts{
32+
Name: generateName("server_volume_attachment_count"),
33+
Help: "Server volume attachment count",
34+
},
35+
serverLabels,
36+
)
37+
38+
prometheus.MustRegister(serverStatus)
39+
prometheus.MustRegister(serverVolumeAttachmentCount)
40+
}
41+
42+
// PublishServerMetrics makes the list request to the server api and
43+
// passes the result to a publish function.
44+
func PublishServerMetrics(client *gophercloud.ServiceClient, tenantID string) error {
45+
// first step: gather the data
46+
mc := newOpenStackMetric("server", "list")
47+
pages, err := servers.List(client, servers.ListOpts{}).AllPages()
48+
if mc.Observe(err) != nil {
49+
// only warn, maybe the next list will work.
50+
klog.Warningf("Unable to list servers: %v", err)
51+
return err
52+
}
53+
serversList, err := servers.ExtractServers(pages)
54+
if err != nil {
55+
// only warn, maybe the next publish will work.
56+
klog.Warningf("Unable to extract servers: %v", err)
57+
return err
58+
}
59+
60+
// second step: reset the old metrics
61+
serverStatus.Reset()
62+
serverVolumeAttachmentCount.Reset()
63+
64+
// third step: publish the metrics
65+
for _, srv := range serversList {
66+
publishServerMetric(srv)
67+
}
68+
69+
return nil
70+
}
71+
72+
// publishServerMetric extracts data from a server and exposes the metrics via prometheus
73+
func publishServerMetric(srv servers.Server) {
74+
labels := []string{srv.ID}
75+
76+
serverVolumeAttachmentCount.WithLabelValues(labels...).Set(float64(len(srv.AttachedVolumes)))
77+
78+
// create one metric per status
79+
for _, state := range states {
80+
stateLabels := append(labels, state)
81+
serverStatus.WithLabelValues(stateLabels...).Set(boolFloat64(srv.Status == state))
82+
}
83+
}

0 commit comments

Comments
 (0)