Skip to content

Commit

Permalink
Add domain state metricset to kvm module (#17673) (#18052)
Browse files Browse the repository at this point in the history
This allows tracking KVM transitions of state and consolidate
resource usage with machine state.

Signed-off-by: Tom Doherty <tom@singlesecond.com>
(cherry picked from commit ed7fa2a)

Co-authored-by: tomdoherty <31742246+tomdoherty@users.noreply.github.com>
  • Loading branch information
jsoriano and tomdoherty committed May 5, 2020
1 parent 895984b commit 6a2e82e
Show file tree
Hide file tree
Showing 17 changed files with 365 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ https://github.com/elastic/beats/compare/v7.5.0...v7.5.1[View commits]
- Fix docker network stats when multiple interfaces are configured. {issue}14586[14586] {pull}14825[14825]
- Fix ListMetrics pagination in aws module. {issue}14926[14926] {pull}14942[14942]
- Fix CPU count in docker/cpu in cases where no `online_cpus` are reported {pull}15070[15070]
- Add domain state to kvm module {pull}17673[17673]

[[release-notes-7.5.0]]
=== Beats version 7.5.0
Expand Down
44 changes: 44 additions & 0 deletions metricbeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -26936,6 +26936,50 @@ type: long
Domain name


type: keyword

--

[float]
=== status

status



[float]
=== stat

Memory stat



*`kvm.status.stat.state`*::
+
--
domain state


type: keyword

--

*`kvm.status.id`*::
+
--
Domain id


type: long

--

*`kvm.status.name`*::
+
--
Domain name


type: keyword

--
Expand Down
6 changes: 5 additions & 1 deletion metricbeat/docs/modules/kvm.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ in <<configuration-metricbeat>>. Here is an example configuration:
----
metricbeat.modules:
- module: kvm
metricsets: ["dommemstat"]
metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
Expand All @@ -39,5 +39,9 @@ The following metricsets are available:

* <<metricbeat-metricset-kvm-dommemstat,dommemstat>>

* <<metricbeat-metricset-kvm-status,status>>

include::kvm/dommemstat.asciidoc[]

include::kvm/status.asciidoc[]

24 changes: 24 additions & 0 deletions metricbeat/docs/modules/kvm/status.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
////
This file is generated! See scripts/mage/docs_collector.go
////

[[metricbeat-metricset-kvm-status]]
=== kvm status metricset

beta[]

include::../../../module/kvm/status/_meta/docs.asciidoc[]

This is a default metricset. If the host module is unconfigured, this metricset is enabled by default.

==== Fields

For a description of each field in the metricset, see the
<<exported-fields-kvm,exported fields>> section.

Here is an example document generated by this metricset:

[source,json]
----
include::../../../module/kvm/status/_meta/data.json[]
----
3 changes: 2 additions & 1 deletion metricbeat/docs/modules_list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ This file is generated! See scripts/mage/docs_collector.go
|<<metricbeat-metricset-kubernetes-system,system>>
|<<metricbeat-metricset-kubernetes-volume,volume>>
|<<metricbeat-module-kvm,kvm>> beta[] |image:./images/icon-no.png[No prebuilt dashboards] |
.1+| .1+| |<<metricbeat-metricset-kvm-dommemstat,dommemstat>> beta[]
.2+| .2+| |<<metricbeat-metricset-kvm-dommemstat,dommemstat>> beta[]
|<<metricbeat-metricset-kvm-status,status>> beta[]
|<<metricbeat-module-logstash,Logstash>> |image:./images/icon-no.png[No prebuilt dashboards] |
.2+| .2+| |<<metricbeat-metricset-logstash-node,node>>
|<<metricbeat-metricset-logstash-node_stats,node_stats>>
Expand Down
1 change: 1 addition & 0 deletions metricbeat/include/list_common.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion metricbeat/metricbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,7 @@ metricbeat.modules:

#--------------------------------- Kvm Module ---------------------------------
- module: kvm
metricsets: ["dommemstat"]
metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/module/kvm/_meta/config.reference.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
- module: kvm
metricsets: ["dommemstat"]
metricsets: ["dommemstat", "status"]
enabled: true
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
Expand Down
1 change: 1 addition & 0 deletions metricbeat/module/kvm/_meta/config.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
- module: kvm
#metricsets:
# - dommemstat
# - status
period: 10s
hosts: ["unix:///var/run/libvirt/libvirt-sock"]
2 changes: 1 addition & 1 deletion metricbeat/module/kvm/fields.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions metricbeat/module/kvm/status/_meta/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"@timestamp": "2017-10-12T08:05:34.853Z",
"agent": {
"hostname": "host.example.com",
"name": "host.example.com"
},
"event":{
"dataset":"kvm.status",
"module":"kvm",
"duration":4012216
},
"metricset":{
"name":"status"
},
"service":{
"address":"unix:///var/run/libvirt/libvirt-sock",
"type":"kvm"
},
"kvm":{
"status":{
"stat":{
"state":"running"
},
"id":1,
"name":"generic-2"
}
}
}
1 change: 1 addition & 0 deletions metricbeat/module/kvm/status/_meta/docs.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is the status metricset of the module kvm.
23 changes: 23 additions & 0 deletions metricbeat/module/kvm/status/_meta/fields.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
- name: status
type: group
description: >
status
release: beta
fields:
- name: stat
type: group
description: >
Memory stat
fields:
- name: state
type: keyword
description: >
domain state
- name: id
type: long
description: >
Domain id
- name: name
type: keyword
description: >
Domain name
161 changes: 161 additions & 0 deletions metricbeat/module/kvm/status/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package status

import (
"net"
"net/url"
"time"

"github.com/pkg/errors"

"github.com/digitalocean/go-libvirt"
"github.com/digitalocean/go-libvirt/libvirttest"

"github.com/elastic/beats/v7/libbeat/common"
"github.com/elastic/beats/v7/libbeat/common/cfgwarn"
"github.com/elastic/beats/v7/metricbeat/mb"
)

// init registers the MetricSet with the central registry as soon as the program
// starts. The New function will be called later to instantiate an instance of
// the MetricSet for each host defined in the module's configuration. After the
// MetricSet has been created then Fetch will begin to be called periodically.
func init() {
mb.Registry.MustAddMetricSet("kvm", "status", New,
mb.DefaultMetricSet(),
)
}

// MetricSet holds any configuration or state information. It must implement
// the mb.MetricSet interface. And this is best achieved by embedding
// mb.BaseMetricSet because it implements all of the required mb.MetricSet
// interface methods except for Fetch.
type MetricSet struct {
mb.BaseMetricSet
Timeout time.Duration
HostURL *url.URL
}

// New creates a new instance of the MetricSet. New is responsible for unpacking
// any MetricSet specific configuration options if there are any.
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
cfgwarn.Beta("The kvm status metricset is beta.")
u, err := url.Parse(base.HostData().URI)
if err != nil {
return nil, err
}

return &MetricSet{
BaseMetricSet: base,
Timeout: base.Module().Config().Timeout,
HostURL: u,
}, nil
}

// Fetch methods implements the data gathering and data conversion to the right
// format. It publishes the event which is then forwarded to the output. In case
// of an error set the Error field of mb.Event or simply call report.Error().
func (m *MetricSet) Fetch(report mb.ReporterV2) error {
var (
c net.Conn
err error
)

u := m.HostURL

if u.Scheme == "test" {
// when running tests, a mock Libvirt server is used
c = libvirttest.New()
} else {
address := u.Host
if u.Host == "" {
address = u.Path
}

c, err = net.DialTimeout(u.Scheme, address, m.Timeout)
if err != nil {
return errors.Wrapf(err, "cannot connect to %v", u)
}
}

defer c.Close()

l := libvirt.New(c)
if err = l.Connect(); err != nil {
return errors.Wrap(err, "error connecting to libvirtd")
}
defer func() {
if err = l.Disconnect(); err != nil {
msg := errors.Wrap(err, "failed to disconnect")
report.Error(msg)
m.Logger().Error(msg)
}
}()

domains, err := l.Domains()
if err != nil {
return errors.Wrap(err, "error listing domains")
}

for _, d := range domains {
state, err := l.DomainState(d.Name)
if err != nil {
continue
}
reported := report.Event(mb.Event{
ModuleFields: common.MapStr{
"id": d.ID,
"name": d.Name,
},
MetricSetFields: common.MapStr{
"stat": common.MapStr{
"state": getDomainStateName(state),
},
},
})
if !reported {
return nil
}
}

return nil
}

func getDomainStateName(tag libvirt.DomainState) string {
switch tag {
case 0:
return "no state"
case 1:
return "running"
case 2:
return "blocked"
case 3:
return "paused"
case 4:
return "shutdown"
case 5:
return "shutoff"
case 6:
return "crashed"
case 7:
return "suspended"
default:
return "unidentified"
}
}
Loading

0 comments on commit 6a2e82e

Please sign in to comment.