Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metricbeat: Add munin module #6517

Merged
merged 1 commit into from
Mar 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ https://github.com/elastic/beats/compare/v6.0.0-beta2...master[Check the HEAD di
- Making the jolokia/jmx module GA. {pull}6143[6143]
- Making the MongoDB module GA. {pull}6554[6554]
- Allow to disable labels `dedot` in Docker module, in favor of a safe way to keep dots. {pull}6490[6490]
- Add experimental module to collect metrics from munin nodes. {pull}6517[6517]

*Packetbeat*

Expand Down
4 changes: 4 additions & 0 deletions metricbeat/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ services:
- ./module/logstash/_meta/env
- ./module/memcached/_meta/env
- ./module/mongodb/_meta/env
- ./module/munin/_meta/env
- ./module/mysql/_meta/env
- ./module/nginx/_meta/env
- ./module/php_fpm/_meta/env
Expand Down Expand Up @@ -107,6 +108,9 @@ services:
mongodb:
build: ./module/mongodb/_meta

munin:
build: ./module/munin/_meta

mysql:
build: ./module/mysql/_meta

Expand Down
16 changes: 16 additions & 0 deletions metricbeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ grouped in the following categories:
* <<exported-fields-logstash>>
* <<exported-fields-memcached>>
* <<exported-fields-mongodb>>
* <<exported-fields-munin>>
* <<exported-fields-mysql>>
* <<exported-fields-nginx>>
* <<exported-fields-php_fpm>>
Expand Down Expand Up @@ -7656,6 +7657,21 @@ type: long
Number of sync operations.


[[exported-fields-munin]]
== Munin fields

experimental[]
Munin node metrics exporter



[float]
== munin fields

munin contains metrics exposed by a munin node agent



[[exported-fields-mysql]]
== MySQL fields

Expand Down
41 changes: 41 additions & 0 deletions metricbeat/docs/modules/munin.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
////
This file is generated! See scripts/docs_collector.py
////

[[metricbeat-module-munin]]
== Munin module

experimental[]

== munin module

This is the munin module.



[float]
=== Example configuration

The Munin module supports the standard configuration options that are described
in <<configuration-metricbeat>>. Here is an example configuration:

[source,yaml]
----
metricbeat.modules:
- module: munin
metricsets: ["node"]
enabled: false
period: 10s
hosts: ["localhost:4949"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace config

node.namespace: node
----

[float]
=== Metricsets

The following metricsets are available:

* <<metricbeat-metricset-munin-node,node>>

include::munin/node.asciidoc[]

17 changes: 17 additions & 0 deletions metricbeat/docs/modules/munin/node.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
////
This file is generated! See scripts/docs_collector.py
////

[[metricbeat-metricset-munin-node]]
=== Munin node metricset

experimental[]

include::../../../module/munin/node/_meta/docs.asciidoc[]


==== Fields

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

3 changes: 3 additions & 0 deletions metricbeat/docs/modules_list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ This file is generated! See scripts/docs_collector.py
.3+| |<<metricbeat-metricset-mongodb-collstats,collstats>>
|<<metricbeat-metricset-mongodb-dbstats,dbstats>>
|<<metricbeat-metricset-mongodb-status,status>>
|<<metricbeat-module-munin,Munin>> experimental[] |
.1+| |<<metricbeat-metricset-munin-node,node>> experimental[]
|<<metricbeat-module-mysql,MySQL>> |
.1+| |<<metricbeat-metricset-mysql-status,status>>
|<<metricbeat-module-nginx,Nginx>> |
Expand Down Expand Up @@ -147,6 +149,7 @@ include::modules/kubernetes.asciidoc[]
include::modules/logstash.asciidoc[]
include::modules/memcached.asciidoc[]
include::modules/mongodb.asciidoc[]
include::modules/munin.asciidoc[]
include::modules/mysql.asciidoc[]
include::modules/nginx.asciidoc[]
include::modules/php_fpm.asciidoc[]
Expand Down
2 changes: 2 additions & 0 deletions metricbeat/include/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import (
_ "github.com/elastic/beats/metricbeat/module/mongodb/collstats"
_ "github.com/elastic/beats/metricbeat/module/mongodb/dbstats"
_ "github.com/elastic/beats/metricbeat/module/mongodb/status"
_ "github.com/elastic/beats/metricbeat/module/munin"
_ "github.com/elastic/beats/metricbeat/module/munin/node"
_ "github.com/elastic/beats/metricbeat/module/mysql"
_ "github.com/elastic/beats/metricbeat/module/mysql/status"
_ "github.com/elastic/beats/metricbeat/module/nginx"
Expand Down
8 changes: 8 additions & 0 deletions metricbeat/metricbeat.reference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,14 @@ metricbeat.modules:
# Password to use when connecting to MongoDB. Empty by default.
#password: pass

#-------------------------------- Munin Module -------------------------------
- module: munin
metricsets: ["node"]
enabled: false
period: 10s
hosts: ["localhost:4949"]
node.namespace: node

#-------------------------------- MySQL Module -------------------------------
- module: mysql
metricsets: ["status"]
Expand Down
13 changes: 13 additions & 0 deletions metricbeat/module/munin/_meta/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM ubuntu:16.04

RUN apt-get update && \
apt-get install -y munin-node netcat && \
apt-get clean && rm rm -rf /var/lib/apt/lists/*

EXPOSE 4949

COPY munin-node.conf /etc/munin/munin-node.conf

HEALTHCHECK --interval=1s --retries=90 CMD nc -z 127.0.0.1 4949

CMD munin-node
6 changes: 6 additions & 0 deletions metricbeat/module/munin/_meta/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- module: munin
metricsets: ["node"]
enabled: false
period: 10s
hosts: ["localhost:4949"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add namespace config.

node.namespace: node
4 changes: 4 additions & 0 deletions metricbeat/module/munin/_meta/docs.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
== munin module

This is the munin module.

2 changes: 2 additions & 0 deletions metricbeat/module/munin/_meta/env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MUNIN_HOST=munin
MUNIN_PORT=4949
13 changes: 13 additions & 0 deletions metricbeat/module/munin/_meta/fields.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- key: munin
title: "Munin"
description: >
experimental[]

Munin node metrics exporter
release: experimental
fields:
- name: munin
type: group
description: >
munin contains metrics exposed by a munin node agent
fields:
15 changes: 15 additions & 0 deletions metricbeat/module/munin/_meta/munin-node.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
setsid 0

ignore_file [\#~]$
ignore_file DEADJOE$
ignore_file \.bak$
ignore_file %$
ignore_file \.dpkg-(tmp|new|old|dist)$
ignore_file \.rpm(save|new)$
ignore_file \.pod$

allow .*

host 0.0.0.0

port 4949
2 changes: 2 additions & 0 deletions metricbeat/module/munin/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package munin is a Metricbeat module that contains MetricSets.
package munin
115 changes: 115 additions & 0 deletions metricbeat/module/munin/munin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package munin

import (
"bufio"
"fmt"
"io"
"net"
"strconv"
"strings"
"time"

"github.com/joeshaw/multierror"
"github.com/pkg/errors"

"github.com/elastic/beats/libbeat/common"
)

const (
unknownValue = "U"
)

// Node connection
type Node struct {
conn net.Conn

writer io.Writer
reader *bufio.Reader
}

// Connect with a munin node
func Connect(address string, timeout time.Duration) (*Node, error) {
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
return nil, err
}
n := &Node{conn: conn,
writer: conn,
reader: bufio.NewReader(conn),
}
// Cosume and ignore first line returned by munin, it is a comment
// about the node
scanner := bufio.NewScanner(n.reader)
scanner.Scan()
return n, scanner.Err()
}

// Close node connection relasing its resources
func (n *Node) Close() error {
return n.conn.Close()
}

// List of items exposed by the node
func (n *Node) List() ([]string, error) {
_, err := io.WriteString(n.writer, "list\n")
if err != nil {
return nil, err
}

scanner := bufio.NewScanner(n.reader)
scanner.Scan()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also check here the return value?

return strings.Fields(scanner.Text()), scanner.Err()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you run here scanner.Err() which makes the return value check obsolete before.

}

// Fetch metrics from munin node
func (n *Node) Fetch(items ...string) (common.MapStr, error) {
var errs multierror.Errors
event := common.MapStr{}

for _, item := range items {
_, err := io.WriteString(n.writer, "fetch "+item+"\n")
if err != nil {
errs = append(errs, err)
continue
}

scanner := bufio.NewScanner(n.reader)
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
name := strings.TrimSpace(scanner.Text())

// Munin delimites metrics with a dot
if name == "." {
break
}

name = strings.TrimSuffix(name, ".value")

if !scanner.Scan() {
if scanner.Err() == nil {
errs = append(errs, errors.New("unexpected EOF when expecting value"))
}
break
}
value := scanner.Text()

key := fmt.Sprintf("%s.%s", item, name)

if value == unknownValue {
errs = append(errs, errors.Errorf("unknown value for %s", key))
continue
}
if f, err := strconv.ParseFloat(value, 64); err == nil {
event.Put(key, f)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the record, this is a candidate for safemapstr.Put: #6434 as soon as it's in

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, the PR went in already, so you can update these :)

Copy link
Member Author

@jsoriano jsoriano Mar 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, but I think dots are not allowed in munin metric names.
We could use safemapstr in any case to protect metricbeat against incorrect implementations of munin nodes or plugins, wdyt?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if the float parsing will make a difference in ES. If we have a value 3 and we parse it it will still put 3 into the event and on the ES side it will assume it's an integer so conflicts will happen afterwards. Sounds like a good use case for the local fields definitions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Umm, so what do you recommend to do here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've checked metrics format, sounds like we don't need safemapstr.Put here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what I'm getting at we could even skip this code part here and it would make no difference? If someone wants to make sure the mapping is correct he has to use #6024

Please double check the above statement as I don't know much about the munin output.

continue
}
event.Put(key, value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safemapstr.Put too

}

if scanner.Err() != nil {
errs = append(errs, scanner.Err())
}
}

return event, errs.Err()
}
Loading