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 Prototype #611

Merged
merged 1 commit into from
Feb 8, 2016
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
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ env:
- TARGETS="-C filebeat testsuite"
- TARGETS="-C winlogbeat testsuite"
- TARGETS="-C packetbeat testsuite"
- TARGETS="-C metricbeat testsuite"
- TARGETS="-C libbeat crosscompile"
- TARGETS="-C winlogbeat crosscompile"
global:
Expand All @@ -41,6 +42,8 @@ matrix:
env: TARGETS="-C winlogbeat crosscompile"
- os: osx
env: TARGETS="-C libbeat testsuite"
- os: osx
env: TARGETS="-C metricbeat testsuite"
fast_finish: true
allow_failures:
- env: TARGETS="-C libbeat crosscompile"
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BUILD_DIR=build
COVERAGE_DIR=${BUILD_DIR}/coverage
BEATS=packetbeat topbeat filebeat winlogbeat
BEATS=packetbeat topbeat filebeat winlogbeat metricbeat
PROJECTS=libbeat ${BEATS}

# Runs complete testsuites (unit, system, integration) for all beats,
Expand Down
1 change: 1 addition & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import:
- package: github.com/samuel/go-parser
- package: github.com/samuel/go-thrift
version: 2187045faa54fce7f5028706ffeb2f2fc342aa7e
# Alternative name? gopkg.in/mgo.v2 https://github.com/Masterminds/glide/issues/221#issuecomment-179817757
- package: labix.org/v2/mgo
- package: github.com/tsg/gopacket
- package: github.com/joeshaw/multierror
Expand Down
12 changes: 8 additions & 4 deletions libbeat/scripts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ ARCH?=$(shell uname -m)
export PATH := ./bin:$(PATH)
export GO15VENDOREXPERIMENT=1
GOFILES = $(shell find . -type f -name '*.go')
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*")
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "*/vendor/*")
SHELL=bash
ES_HOST?="elasticsearch"
BUILD_DIR?=$(shell pwd)/build
Expand All @@ -44,7 +44,7 @@ PYTHON_ENV?=${BUILD_DIR}/python-env

# Conditionally enable the race detector when RACE_DETECTOR=1.
ifeq ($(RACE_DETECTOR),1)
RACE=-race
RACE=-race
endif


Expand Down Expand Up @@ -181,7 +181,11 @@ testsuite:

# Runs system tests if SYSTEM_TESTS is set to true
if [ $(SYSTEM_TESTS) = true ]; then \
$(MAKE) system-tests; \
if [ $(TEST_ENVIRONMENT) = true ]; then \
${DOCKER_COMPOSE} run beat make system-tests; \
else \
$(MAKE) system-tests; \
fi \
fi

$(MAKE) benchmark-tests
Expand Down Expand Up @@ -214,7 +218,7 @@ build-image: write-environment
# To use it for running the test, set ES_HOST and REDIS_HOST environment variable to the ip of your docker-machine.
.PHONY: start-environment
start-environment: stop-environment
${DOCKER_COMPOSE} up -d redis elasticsearch logstash
${DOCKER_COMPOSE} up -d

.PHONY: stop-environment
stop-environment:
Expand Down
4 changes: 4 additions & 0 deletions metricbeat/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
build

/metricbeat
/metricbeat.test
1 change: 1 addition & 0 deletions metricbeat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is only a temporary changelog to keep track of changes until the first release for contributors.
23 changes: 23 additions & 0 deletions metricbeat/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM golang:1.5.3
MAINTAINER Nicolas Ruflin <ruflin@elastic.co>

RUN set -x && \
apt-get update && \
apt-get install -y netcat python-virtualenv python-pip && \
apt-get clean


## Install go package dependencies
RUN set -x \
go get \
github.com/pierrre/gotestcover \
github.com/tsg/goautotest \
golang.org/x/tools/cmd/cover \
golang.org/x/tools/cmd/vet

# Setup work environment
ENV METRICBEAT_PATH /go/src/github.com/elastic/beats/metricbeat
ENV GO15VENDOREXPERIMENT=1

RUN mkdir -p $METRICBEAT_PATH/build/coverage
WORKDIR $METRICBEAT_PATH
7 changes: 7 additions & 0 deletions metricbeat/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

BEATNAME=metricbeat
SYSTEM_TESTS=true
TEST_ENVIRONMENT?=true

include ../libbeat/scripts/Makefile
23 changes: 23 additions & 0 deletions metricbeat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Metricbeat

Metricbeat takes metrics and statistics from your systems and ships them to elasticsearch or logstash.

**WARNING: Metricbeat is currently still in an experimental phase and under heavy development.**

## Usage

Metricbeat should be installed as local as possible so it can fetch metrics directly from the intended systems. For example if there are multiple MySQL servers, Metricbeat should be installed on each machine if possible instead of a centralised installation.

## Contributions

Contributions of new modules and metricsets to Metricbeat are highly welcome. To guarantee the quality of all metricsets we defined the following requirements for each Metricset:

* Unit tests
* Integration tests
* Kibana Dashboards
* Template

Best is to start your own module as its own beat first (see below use it as a library) so you can test it and then start a discussion with our team if it would fit into Metricbeat.

## Use it as library
Metricbeat can also be used as a library so you can implement your own module on top of metricbeat and building your own beat based on it, withouth getting your module into the main repository. This allows to make use of the schedule and interfaces of Metricbeat. A developer guide and how to do this will follow soon.
13 changes: 13 additions & 0 deletions metricbeat/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
List of things to keep track on:

* Create dashboard for each implemented metricset
* validate schema with topbeat -> will it work as expected
* send also document if remote system is not reachable -> error document
* What happens on error of fetch?
* disable _all for all fields
* disable _source? for all fields
* Filters on metricset level
* Idea: Basic, Medium, All data to have predefined sets / levels
* Or is this done via filter implementation
* Add fields per module / metricsets
* Improve apache docker image
30 changes: 30 additions & 0 deletions metricbeat/beater/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package beater

import (
"github.com/elastic/beats/metricbeat/helper"
)

type MetricbeatConfig struct {
Metricbeat helper.ModulesConfig
}

// Raw module config to be processed later by the module
type RawModulesConfig struct {
Metricbeat struct {
Modules map[string]interface{}
}
}

// Raw metric config to be processed later by the metric
type RawMetricsConfig struct {
Metricbeat struct {
Modules map[string]struct {
MetricSets map[string]interface{} `yaml:"metricsets"`
}
}
}

// getModuleConfig returns config for the specified module
func (config *MetricbeatConfig) getModuleConfig(moduleName string) helper.ModuleConfig {
return config.Metricbeat.Modules[moduleName]
}
120 changes: 120 additions & 0 deletions metricbeat/beater/metricbeat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*

Metricbeat collects metric sets from different modules.


Each event created has the following format:

curl -XPUT http://localhost:9200/metricbeat/metricsets -d
{
"metriset": metricsetName,
"module": moduleName,
"moduleName-metricSetName": {
"metric1": "value",
"metric2": "value",
"metric3": "value",
"nestedmetric": {
"metric4": "value"
}
},
"@timestamp": timestamp
}

All documents are currently stored in one index called metricbeat. It is important to use an independent namespace
for each MetricSet to prevent type conflicts. Also all values are stored under the same type "metricsets".

*/
package beater

import (
"fmt"

"github.com/elastic/beats/libbeat/beat"
"github.com/elastic/beats/libbeat/cfgfile"
"github.com/elastic/beats/libbeat/logp"
"github.com/elastic/beats/metricbeat/helper"
)

type Metricbeat struct {
done chan struct{}
MbConfig *MetricbeatConfig
ModulesConfig *RawModulesConfig
MetricsConfig *RawMetricsConfig
}

// New creates a new Metricbeat instance
func New() *Metricbeat {
return &Metricbeat{}
}

func (mb *Metricbeat) Config(b *beat.Beat) error {

mb.MbConfig = &MetricbeatConfig{}
err := cfgfile.Read(mb.MbConfig, "")
if err != nil {
fmt.Println(err)
logp.Err("Error reading configuration file: %v", err)
return err
}

mb.ModulesConfig = &RawModulesConfig{}
err = cfgfile.Read(mb.ModulesConfig, "")
if err != nil {
fmt.Println(err)
logp.Err("Error reading configuration file: %v", err)
return err
}

mb.MetricsConfig = &RawMetricsConfig{}
err = cfgfile.Read(mb.MetricsConfig, "")
if err != nil {
fmt.Println(err)
logp.Err("Error reading configuration file: %v", err)
return err
}

logp.Info("Setup base and raw configuration for Modules and Metrics")
// Apply the base configuration to each module and metric
for moduleName, module := range helper.Registry {
// Check if config for module exist. Only configured modules are loaded
if _, ok := mb.MbConfig.Metricbeat.Modules[moduleName]; !ok {
continue
}
module.BaseConfig = mb.MbConfig.getModuleConfig(moduleName)
module.RawConfig = mb.ModulesConfig.Metricbeat.Modules[moduleName]
module.Enabled = true

for metricSetName, metricSet := range module.MetricSets {
// Check if config for metricset exist. Only configured metricset are loaded
if _, ok := mb.MbConfig.getModuleConfig(moduleName).MetricSets[metricSetName]; !ok {
continue
}
metricSet.BaseConfig = mb.MbConfig.getModuleConfig(moduleName).MetricSets[metricSetName]
metricSet.RawConfig = mb.MetricsConfig.Metricbeat.Modules[moduleName].MetricSets[metricSetName]
metricSet.Enabled = true
}
}

return nil
}

func (mb *Metricbeat) Setup(b *beat.Beat) error {
mb.done = make(chan struct{})
return nil
}

func (mb *Metricbeat) Run(b *beat.Beat) error {

helper.StartModules(b)
<-mb.done

return nil
}

func (mb *Metricbeat) Cleanup(b *beat.Beat) error {
return nil
}

func (mb *Metricbeat) Stop() {
close(mb.done)
}
36 changes: 36 additions & 0 deletions metricbeat/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
beat:
build: .
links:
- apache
- elasticsearch
- mysql
- redis
environment:
- APACHE_HOST=apache
- APACHE_PORT=80
- REDIS_HOST=redis
- REDIS_PORT=6379
- MYSQL_DSN=root:test@tcp(mysql:3306)/
- MYSQL_HOST=mysql
- MYSQL_PORT=3306
- TEST_ENVIRONMENT=false
working_dir: /go/src/github.com/elastic/beats/metricbeat
volumes:
- ..:/go/src/github.com/elastic/beats/
command: make
entrypoint: /go/src/github.com/elastic/beats/metricbeat/docker-entrypoint.sh
elasticsearch:
image: elasticsearch:2.1.0
command: elasticsearch -Des.network.host=0.0.0.0

# Modules
apache:
build: tests/environments/apache

mysql:
image: mysql:5.7.10
environment:
- MYSQL_ROOT_PASSWORD=test

redis:
image: redis:3.0.6
Loading