Merge pull request #2 from KPACHbIuLLIAnO4/master
merge changes from influxdb
This commit is contained in:
commit
edf1336f8f
19
CHANGELOG.md
19
CHANGELOG.md
|
@ -1,4 +1,21 @@
|
||||||
## v0.1.8 [unreleased]
|
## v0.1.9 [unreleased]
|
||||||
|
|
||||||
|
### Release Notes
|
||||||
|
- InfluxDB output config change: `url` is now `urls`, and is a list. Config files
|
||||||
|
will still be backwards compatible if only `url` is specified.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- [#143](https://github.com/influxdb/telegraf/issues/143): InfluxDB clustering support
|
||||||
|
- [#181](https://github.com/influxdb/telegraf/issues/181): Makefile GOBIN support. Thanks @Vye!
|
||||||
|
|
||||||
|
### Bugfixes
|
||||||
|
- [#170](https://github.com/influxdb/telegraf/issues/170): Systemd support
|
||||||
|
- [#175](https://github.com/influxdb/telegraf/issues/175): Set write precision before gathering metrics
|
||||||
|
- [#178](https://github.com/influxdb/telegraf/issues/178): redis plugin, multiple server thread hang bug
|
||||||
|
- Fix net plugin on darwin
|
||||||
|
- [#84](https://github.com/influxdb/telegraf/issues/84): Fix docker plugin on CentOS. Thanks @neezgee!
|
||||||
|
|
||||||
|
## v0.1.8 [2015-09-04]
|
||||||
|
|
||||||
### Release Notes
|
### Release Notes
|
||||||
- Telegraf will now write data in UTC at second precision by default
|
- Telegraf will now write data in UTC at second precision by default
|
||||||
|
|
|
@ -128,3 +128,36 @@ func init() {
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
TODO: this section will describe requirements for contributing an output
|
TODO: this section will describe requirements for contributing an output
|
||||||
|
|
||||||
|
## Unit Tests
|
||||||
|
|
||||||
|
### Execute short tests
|
||||||
|
|
||||||
|
execute `make test-short`
|
||||||
|
|
||||||
|
### Execute long tests
|
||||||
|
|
||||||
|
As Telegraf collects metrics from several third-party services it becomes a
|
||||||
|
difficult task to mock each service as some of them have complicated protocols
|
||||||
|
which would take some time to replicate.
|
||||||
|
|
||||||
|
To overcome this situation we've decided to use docker containers to provide a
|
||||||
|
fast and reproducible environment to test those services which require it.
|
||||||
|
For other situations
|
||||||
|
(i.e: https://github.com/influxdb/telegraf/blob/master/plugins/redis/redis_test.go )
|
||||||
|
a simple mock will suffice.
|
||||||
|
|
||||||
|
To execute Telegraf tests follow these simple steps:
|
||||||
|
|
||||||
|
- Install docker compose following [these](https://docs.docker.com/compose/install/)
|
||||||
|
instructions
|
||||||
|
- execute `make test`
|
||||||
|
|
||||||
|
**OSX users**: you will need to install `boot2docker` or `docker-machine`.
|
||||||
|
The Makefile will assume that you have a `docker-machine` box called `default` to
|
||||||
|
get the IP address.
|
||||||
|
|
||||||
|
### Unit test troubleshooting
|
||||||
|
|
||||||
|
Try cleaning up your test environment by executing `make test-cleanup` and
|
||||||
|
re-running
|
||||||
|
|
22
Makefile
22
Makefile
|
@ -1,19 +1,22 @@
|
||||||
UNAME := $(shell sh -c 'uname')
|
UNAME := $(shell sh -c 'uname')
|
||||||
VERSION := $(shell sh -c 'git describe --always --tags')
|
VERSION := $(shell sh -c 'git describe --always --tags')
|
||||||
|
ifndef GOBIN
|
||||||
|
GOBIN = $(GOPATH)/bin
|
||||||
|
endif
|
||||||
|
|
||||||
build: prepare
|
build: prepare
|
||||||
$(GOPATH)/bin/godep go build -o telegraf -ldflags \
|
$(GOBIN)/godep go build -o telegraf -ldflags \
|
||||||
"-X main.Version $(VERSION)" \
|
"-X main.Version $(VERSION)" \
|
||||||
./cmd/telegraf/telegraf.go
|
./cmd/telegraf/telegraf.go
|
||||||
|
|
||||||
build-linux-bins: prepare
|
build-linux-bins: prepare
|
||||||
GOARCH=amd64 GOOS=linux $(GOPATH)/bin/godep go build -o telegraf_linux_amd64 \
|
GOARCH=amd64 GOOS=linux $(GOBIN)/godep go build -o telegraf_linux_amd64 \
|
||||||
-ldflags "-X main.Version $(VERSION)" \
|
-ldflags "-X main.Version $(VERSION)" \
|
||||||
./cmd/telegraf/telegraf.go
|
./cmd/telegraf/telegraf.go
|
||||||
GOARCH=386 GOOS=linux $(GOPATH)/bin/godep go build -o telegraf_linux_386 \
|
GOARCH=386 GOOS=linux $(GOBIN)/godep go build -o telegraf_linux_386 \
|
||||||
-ldflags "-X main.Version $(VERSION)" \
|
-ldflags "-X main.Version $(VERSION)" \
|
||||||
./cmd/telegraf/telegraf.go
|
./cmd/telegraf/telegraf.go
|
||||||
GOARCH=arm GOOS=linux $(GOPATH)/bin/godep go build -o telegraf_linux_arm \
|
GOARCH=arm GOOS=linux $(GOBIN)/godep go build -o telegraf_linux_arm \
|
||||||
-ldflags "-X main.Version $(VERSION)" \
|
-ldflags "-X main.Version $(VERSION)" \
|
||||||
./cmd/telegraf/telegraf.go
|
./cmd/telegraf/telegraf.go
|
||||||
|
|
||||||
|
@ -22,19 +25,20 @@ prepare:
|
||||||
|
|
||||||
docker-compose:
|
docker-compose:
|
||||||
ifeq ($(UNAME), Darwin)
|
ifeq ($(UNAME), Darwin)
|
||||||
ADVERTISED_HOST=$(shell sh -c 'boot2docker ip') docker-compose up -d
|
ADVERTISED_HOST=$(shell sh -c 'boot2docker ip || docker-machine ip default') \
|
||||||
|
docker-compose --file scripts/docker-compose.yml up -d
|
||||||
endif
|
endif
|
||||||
ifeq ($(UNAME), Linux)
|
ifeq ($(UNAME), Linux)
|
||||||
ADVERTISED_HOST=localhost docker-compose up -d
|
ADVERTISED_HOST=localhost docker-compose --file scripts/docker-compose.yml up -d
|
||||||
endif
|
endif
|
||||||
|
|
||||||
test: prepare docker-compose
|
test: prepare docker-compose
|
||||||
$(GOPATH)/bin/godep go test -v ./...
|
$(GOBIN)/godep go test -v ./...
|
||||||
|
|
||||||
test-short: prepare
|
test-short: prepare
|
||||||
$(GOPATH)/bin/godep go test -short ./...
|
$(GOBIN)/godep go test -short ./...
|
||||||
|
|
||||||
test-cleanup:
|
test-cleanup:
|
||||||
docker-compose kill
|
docker-compose --file scripts/docker-compose.yml kill
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
|
|
95
README.md
95
README.md
|
@ -1,46 +1,58 @@
|
||||||
# Telegraf - A native agent for InfluxDB [![Circle CI](https://circleci.com/gh/influxdb/telegraf.svg?style=svg)](https://circleci.com/gh/influxdb/telegraf)
|
# Telegraf - A native agent for InfluxDB [![Circle CI](https://circleci.com/gh/influxdb/telegraf.svg?style=svg)](https://circleci.com/gh/influxdb/telegraf)
|
||||||
|
|
||||||
Telegraf is an agent written in Go for collecting metrics from the system it's
|
Telegraf is an agent written in Go for collecting metrics from the system it's
|
||||||
running on or from other services and writing them into InfluxDB.
|
running on, or from other services, and writing them into InfluxDB.
|
||||||
|
|
||||||
Design goals are to have a minimal memory footprint with a plugin system so
|
Design goals are to have a minimal memory footprint with a plugin system so
|
||||||
that developers in the community can easily add support for collecting metrics
|
that developers in the community can easily add support for collecting metrics
|
||||||
from well known services (like Hadoop, or Postgres, or Redis) and third party
|
from well known services (like Hadoop, Postgres, or Redis) and third party
|
||||||
APIs (like Mailchimp, AWS CloudWatch, or Google Analytics).
|
APIs (like Mailchimp, AWS CloudWatch, or Google Analytics).
|
||||||
|
|
||||||
We'll eagerly accept pull requests for new plugins and will manage the set of
|
We'll eagerly accept pull requests for new plugins and will manage the set of
|
||||||
plugins that Telegraf supports. See the bottom of this doc for instructions on
|
plugins that Telegraf supports. See the
|
||||||
|
[contributing guide](CONTRIBUTING.md) for instructions on
|
||||||
writing new plugins.
|
writing new plugins.
|
||||||
|
|
||||||
## Quickstart
|
## Installation:
|
||||||
|
|
||||||
* Build from source or download telegraf:
|
Due to a breaking change to the InfluxDB integer line-protocol, there
|
||||||
|
|
||||||
### Linux packages for Debian/Ubuntu and RHEL/CentOS:
|
|
||||||
|
|
||||||
NOTE: version 0.1.4+ has introduced some breaking changes! A 0.1.4+ telegraf
|
|
||||||
agent is NOT backwards-compatible with a config file from 0.1.3 and below.
|
|
||||||
That being said, the difference is not huge, see below for an example on
|
|
||||||
how to setup the new config file.
|
|
||||||
|
|
||||||
As well, due to a breaking change to the InfluxDB integer line-protocol, there
|
|
||||||
are some InfluxDB compatibility requirements:
|
are some InfluxDB compatibility requirements:
|
||||||
|
|
||||||
* InfluxDB 0.9.3+ (including nightly builds) requires Telegraf 0.1.5+
|
* InfluxDB 0.9.3+ requires Telegraf 0.1.5+
|
||||||
* InfluxDB 0.9.2 and prior requires Telegraf 0.1.4
|
* InfluxDB 0.9.2 and prior requires Telegraf 0.1.4
|
||||||
|
|
||||||
|
### Linux deb and rpm packages:
|
||||||
|
|
||||||
Latest:
|
Latest:
|
||||||
* http://get.influxdb.org/telegraf/telegraf_0.1.8_amd64.deb
|
* http://get.influxdb.org/telegraf/telegraf_0.1.8_amd64.deb
|
||||||
* http://get.influxdb.org/telegraf/telegraf-0.1.8-1.x86_64.rpm
|
* http://get.influxdb.org/telegraf/telegraf-0.1.8-1.x86_64.rpm
|
||||||
|
|
||||||
Binaries:
|
0.1.4:
|
||||||
|
* http://get.influxdb.org/telegraf/telegraf_0.1.4_amd64.deb
|
||||||
|
* http://get.influxdb.org/telegraf/telegraf-0.1.4-1.x86_64.rpm
|
||||||
|
|
||||||
|
##### Package instructions:
|
||||||
|
|
||||||
|
* Telegraf binary is installed in `/opt/telegraf/telegraf`
|
||||||
|
* Telegraf daemon configuration file is in `/etc/opt/telegraf/telegraf.conf`
|
||||||
|
* On sysv systems, the telegraf daemon can be controlled via
|
||||||
|
`service telegraf [action]`
|
||||||
|
* On systemd systems (such as Ubuntu 15+), the telegraf daemon can be
|
||||||
|
controlled via `systemctl [action] telegraf`
|
||||||
|
|
||||||
|
### Linux binaries:
|
||||||
|
|
||||||
|
Latest:
|
||||||
* http://get.influxdb.org/telegraf/telegraf_linux_amd64_0.1.8.tar.gz
|
* http://get.influxdb.org/telegraf/telegraf_linux_amd64_0.1.8.tar.gz
|
||||||
* http://get.influxdb.org/telegraf/telegraf_linux_386_0.1.8.tar.gz
|
* http://get.influxdb.org/telegraf/telegraf_linux_386_0.1.8.tar.gz
|
||||||
* http://get.influxdb.org/telegraf/telegraf_linux_arm_0.1.8.tar.gz
|
* http://get.influxdb.org/telegraf/telegraf_linux_arm_0.1.8.tar.gz
|
||||||
|
|
||||||
0.1.4:
|
##### Binary instructions:
|
||||||
* http://get.influxdb.org/telegraf/telegraf_0.1.4_amd64.deb
|
|
||||||
* http://get.influxdb.org/telegraf/telegraf-0.1.4-1.x86_64.rpm
|
These are standalone binaries that can be unpacked and executed on any linux
|
||||||
|
system. They can be unpacked and renamed in a location such as
|
||||||
|
`/usr/local/bin` for convenience. A config file will need to be generated,
|
||||||
|
see "How to use it" below.
|
||||||
|
|
||||||
### OSX via Homebrew:
|
### OSX via Homebrew:
|
||||||
|
|
||||||
|
@ -62,19 +74,17 @@ if you don't have it already. You also must build with golang version 1.4+
|
||||||
|
|
||||||
### How to use it:
|
### How to use it:
|
||||||
|
|
||||||
* Run `telegraf -sample-config > telegraf.toml` to create an initial configuration
|
* Run `telegraf -sample-config > telegraf.conf` to create an initial configuration
|
||||||
* Edit the configuration to match your needs
|
* Edit the configuration to match your needs
|
||||||
* Run `telegraf -config telegraf.toml -test` to output one full measurement sample to STDOUT
|
* Run `telegraf -config telegraf.conf -test` to output one full measurement sample to STDOUT
|
||||||
* Run `telegraf -config telegraf.toml` to gather and send metrics to configured outputs.
|
* Run `telegraf -config telegraf.conf` to gather and send metrics to configured outputs.
|
||||||
* Run `telegraf -config telegraf.toml -filter system:swap`
|
* Run `telegraf -config telegraf.conf -filter system:swap`
|
||||||
to enable only the system & swap plugins defined in the config.
|
to enable only the system & swap plugins defined in the config.
|
||||||
|
|
||||||
## Telegraf Options
|
## Telegraf Options
|
||||||
|
|
||||||
Telegraf has a few options you can configure under the `agent` section of the
|
Telegraf has a few options you can configure under the `agent` section of the
|
||||||
config. If you don't see an `agent` section run
|
config.
|
||||||
`telegraf -sample-config > telegraf.toml` to create a valid initial
|
|
||||||
configuration:
|
|
||||||
|
|
||||||
* **hostname**: The hostname is passed as a tag. By default this will be
|
* **hostname**: The hostname is passed as a tag. By default this will be
|
||||||
the value retured by `hostname` on the machine running Telegraf.
|
the value retured by `hostname` on the machine running Telegraf.
|
||||||
|
@ -194,36 +204,5 @@ found by running `telegraf -sample-config`
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Please see the
|
Please see the
|
||||||
[contributing guide](https://github.com/influxdb/telegraf/blob/master/CONTRIBUTING.md)
|
[contributing guide](CONTRIBUTING.md)
|
||||||
for details on contributing a plugin or output to Telegraf
|
for details on contributing a plugin or output to Telegraf
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Execute short tests
|
|
||||||
|
|
||||||
execute `make test-short`
|
|
||||||
|
|
||||||
### Execute long tests
|
|
||||||
|
|
||||||
As Telegraf collects metrics from several third-party services it becomes a
|
|
||||||
difficult task to mock each service as some of them have complicated protocols
|
|
||||||
which would take some time to replicate.
|
|
||||||
|
|
||||||
To overcome this situation we've decided to use docker containers to provide a
|
|
||||||
fast and reproducible environment to test those services which require it.
|
|
||||||
For other situations
|
|
||||||
(i.e: https://github.com/influxdb/telegraf/blob/master/plugins/redis/redis_test.go )
|
|
||||||
a simple mock will suffice.
|
|
||||||
|
|
||||||
To execute Telegraf tests follow these simple steps:
|
|
||||||
|
|
||||||
- Install docker compose following [these](https://docs.docker.com/compose/install/)
|
|
||||||
instructions
|
|
||||||
- mac users should be able to simply do `brew install boot2docker`
|
|
||||||
and `brew install docker-compose`
|
|
||||||
- execute `make test`
|
|
||||||
|
|
||||||
### Unit test troubleshooting
|
|
||||||
|
|
||||||
Try cleaning up your test environment by executing `make test-cleanup` and
|
|
||||||
re-running
|
|
||||||
|
|
|
@ -25,7 +25,11 @@ type BatchPoints struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a measurement
|
// Add adds a measurement
|
||||||
func (bp *BatchPoints) Add(measurement string, val interface{}, tags map[string]string) {
|
func (bp *BatchPoints) Add(
|
||||||
|
measurement string,
|
||||||
|
val interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
) {
|
||||||
bp.mu.Lock()
|
bp.mu.Lock()
|
||||||
defer bp.mu.Unlock()
|
defer bp.mu.Unlock()
|
||||||
|
|
||||||
|
|
20
agent.go
20
agent.go
|
@ -84,6 +84,9 @@ func NewAgent(config *Config) (*Agent, error) {
|
||||||
// Connect connects to all configured outputs
|
// Connect connects to all configured outputs
|
||||||
func (a *Agent) Connect() error {
|
func (a *Agent) Connect() error {
|
||||||
for _, o := range a.outputs {
|
for _, o := range a.outputs {
|
||||||
|
if a.Debug {
|
||||||
|
log.Printf("Attempting connection to output: %s\n", o.name)
|
||||||
|
}
|
||||||
err := o.output.Connect()
|
err := o.output.Connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -193,16 +196,17 @@ func (a *Agent) crankParallel() error {
|
||||||
go func(plugin *runningPlugin) {
|
go func(plugin *runningPlugin) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
var acc BatchPoints
|
var bp BatchPoints
|
||||||
acc.Debug = a.Debug
|
bp.Debug = a.Debug
|
||||||
acc.Prefix = plugin.name + "_"
|
bp.Prefix = plugin.name + "_"
|
||||||
acc.Config = plugin.config
|
bp.Config = plugin.config
|
||||||
|
bp.Precision = a.Precision
|
||||||
|
|
||||||
if err := plugin.plugin.Gather(&acc); err != nil {
|
if err := plugin.plugin.Gather(&bp); err != nil {
|
||||||
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
points <- &acc
|
points <- &bp
|
||||||
}(plugin)
|
}(plugin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,6 +234,7 @@ func (a *Agent) crank() error {
|
||||||
var bp BatchPoints
|
var bp BatchPoints
|
||||||
|
|
||||||
bp.Debug = a.Debug
|
bp.Debug = a.Debug
|
||||||
|
bp.Precision = a.Precision
|
||||||
|
|
||||||
for _, plugin := range a.plugins {
|
for _, plugin := range a.plugins {
|
||||||
bp.Prefix = plugin.name + "_"
|
bp.Prefix = plugin.name + "_"
|
||||||
|
@ -245,7 +250,6 @@ func (a *Agent) crank() error {
|
||||||
if a.UTC {
|
if a.UTC {
|
||||||
bp.Time = bp.Time.UTC()
|
bp.Time = bp.Time.UTC()
|
||||||
}
|
}
|
||||||
bp.Precision = a.Precision
|
|
||||||
|
|
||||||
return a.flush(&bp)
|
return a.flush(&bp)
|
||||||
}
|
}
|
||||||
|
@ -263,6 +267,7 @@ func (a *Agent) crankSeparate(shutdown chan struct{}, plugin *runningPlugin) err
|
||||||
|
|
||||||
bp.Prefix = plugin.name + "_"
|
bp.Prefix = plugin.name + "_"
|
||||||
bp.Config = plugin.config
|
bp.Config = plugin.config
|
||||||
|
bp.Precision = a.Precision
|
||||||
|
|
||||||
if err := plugin.plugin.Gather(&bp); err != nil {
|
if err := plugin.plugin.Gather(&bp); err != nil {
|
||||||
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
log.Printf("Error in plugin [%s]: %s", plugin.name, err)
|
||||||
|
@ -274,7 +279,6 @@ func (a *Agent) crankSeparate(shutdown chan struct{}, plugin *runningPlugin) err
|
||||||
if a.UTC {
|
if a.UTC {
|
||||||
bp.Time = bp.Time.UTC()
|
bp.Time = bp.Time.UTC()
|
||||||
}
|
}
|
||||||
bp.Precision = a.Precision
|
|
||||||
|
|
||||||
if err := a.flush(&bp); err != nil {
|
if err := a.flush(&bp); err != nil {
|
||||||
outerr = errors.New("Error encountered processing plugins & outputs")
|
outerr = errors.New("Error encountered processing plugins & outputs")
|
||||||
|
|
|
@ -4,5 +4,5 @@ dependencies:
|
||||||
|
|
||||||
test:
|
test:
|
||||||
override:
|
override:
|
||||||
- bash circle-test.sh
|
- bash scripts/circle-test.sh
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
[outputs]
|
[outputs]
|
||||||
[outputs.influxdb]
|
[outputs.influxdb]
|
||||||
# The full HTTP endpoint URL for your InfluxDB instance
|
# The full HTTP endpoint URL for your InfluxDB instance
|
||||||
url = "http://localhost:8086" # required.
|
urls = ["http://localhost:8086"] # required.
|
||||||
|
|
||||||
# The target database for metrics. This database must already exist
|
# The target database for metrics. This database must already exist
|
||||||
database = "telegraf" # required.
|
database = "telegraf" # required.
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package influxdb
|
package influxdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -12,19 +14,23 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type InfluxDB struct {
|
type InfluxDB struct {
|
||||||
|
// URL is only for backwards compatability
|
||||||
URL string
|
URL string
|
||||||
|
URLs []string `toml:"urls"`
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
Database string
|
Database string
|
||||||
UserAgent string
|
UserAgent string
|
||||||
Timeout t.Duration
|
Timeout t.Duration
|
||||||
|
|
||||||
conn *client.Client
|
conns []*client.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
# The full HTTP endpoint URL for your InfluxDB instance
|
# The full HTTP endpoint URL for your InfluxDB instance
|
||||||
url = "http://localhost:8086" # required.
|
# Multiple urls can be specified for InfluxDB cluster support. Server to
|
||||||
|
# write to will be randomly chosen each interval.
|
||||||
|
urls = ["http://localhost:8086"] # required.
|
||||||
|
|
||||||
# The target database for metrics. This database must already exist
|
# The target database for metrics. This database must already exist
|
||||||
database = "telegraf" # required.
|
database = "telegraf" # required.
|
||||||
|
@ -42,33 +48,58 @@ var sampleConfig = `
|
||||||
`
|
`
|
||||||
|
|
||||||
func (i *InfluxDB) Connect() error {
|
func (i *InfluxDB) Connect() error {
|
||||||
u, err := url.Parse(i.URL)
|
var urls []*url.URL
|
||||||
if err != nil {
|
for _, URL := range i.URLs {
|
||||||
return err
|
u, err := url.Parse(URL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
urls = append(urls, u)
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := client.NewClient(client.Config{
|
// Backward-compatability with single Influx URL config files
|
||||||
URL: *u,
|
// This could eventually be removed in favor of specifying the urls as a list
|
||||||
Username: i.Username,
|
if i.URL != "" {
|
||||||
Password: i.Password,
|
u, err := url.Parse(i.URL)
|
||||||
UserAgent: i.UserAgent,
|
if err != nil {
|
||||||
Timeout: i.Timeout.Duration,
|
return err
|
||||||
})
|
}
|
||||||
|
urls = append(urls, u)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.Query(client.Query{
|
var conns []*client.Client
|
||||||
Command: fmt.Sprintf("CREATE DATABASE %s", i.Database),
|
for _, parsed_url := range urls {
|
||||||
})
|
c, err := client.NewClient(client.Config{
|
||||||
|
URL: *parsed_url,
|
||||||
if err != nil && !strings.Contains(err.Error(), "database already exists") {
|
Username: i.Username,
|
||||||
log.Fatal(err)
|
Password: i.Password,
|
||||||
|
UserAgent: i.UserAgent,
|
||||||
|
Timeout: i.Timeout.Duration,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
conns = append(conns, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
i.conn = c
|
// This will get set to nil if a successful connection is made
|
||||||
return nil
|
err := errors.New("Could not create database on any server")
|
||||||
|
|
||||||
|
for _, conn := range conns {
|
||||||
|
_, e := conn.Query(client.Query{
|
||||||
|
Command: fmt.Sprintf("CREATE DATABASE %s", i.Database),
|
||||||
|
})
|
||||||
|
|
||||||
|
if e != nil && !strings.Contains(e.Error(), "database already exists") {
|
||||||
|
log.Println("ERROR: " + e.Error())
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i.conns = conns
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *InfluxDB) Close() error {
|
func (i *InfluxDB) Close() error {
|
||||||
|
@ -84,12 +115,24 @@ func (i *InfluxDB) Description() string {
|
||||||
return "Configuration for influxdb server to send metrics to"
|
return "Configuration for influxdb server to send metrics to"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose a random server in the cluster to write to until a successful write
|
||||||
|
// occurs, logging each unsuccessful. If all servers fail, return error.
|
||||||
func (i *InfluxDB) Write(bp client.BatchPoints) error {
|
func (i *InfluxDB) Write(bp client.BatchPoints) error {
|
||||||
bp.Database = i.Database
|
bp.Database = i.Database
|
||||||
if _, err := i.conn.Write(bp); err != nil {
|
|
||||||
return err
|
// This will get set to nil if a successful write occurs
|
||||||
|
err := errors.New("Could not write to any InfluxDB server in cluster")
|
||||||
|
|
||||||
|
p := rand.Perm(len(i.conns))
|
||||||
|
for _, n := range p {
|
||||||
|
if _, e := i.conns[n].Write(bp); e != nil {
|
||||||
|
log.Println("ERROR: " + e.Error())
|
||||||
|
} else {
|
||||||
|
err = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -15,9 +15,6 @@ import (
|
||||||
|
|
||||||
type Redis struct {
|
type Redis struct {
|
||||||
Servers []string
|
Servers []string
|
||||||
|
|
||||||
c net.Conn
|
|
||||||
buf []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var sampleConfig = `
|
var sampleConfig = `
|
||||||
|
@ -112,41 +109,37 @@ func (r *Redis) Gather(acc plugins.Accumulator) error {
|
||||||
const defaultPort = "6379"
|
const defaultPort = "6379"
|
||||||
|
|
||||||
func (r *Redis) gatherServer(addr *url.URL, acc plugins.Accumulator) error {
|
func (r *Redis) gatherServer(addr *url.URL, acc plugins.Accumulator) error {
|
||||||
if r.c == nil {
|
_, _, err := net.SplitHostPort(addr.Host)
|
||||||
|
if err != nil {
|
||||||
_, _, err := net.SplitHostPort(addr.Host)
|
addr.Host = addr.Host + ":" + defaultPort
|
||||||
if err != nil {
|
|
||||||
addr.Host = addr.Host + ":" + defaultPort
|
|
||||||
}
|
|
||||||
|
|
||||||
c, err := net.Dial("tcp", addr.Host)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Unable to connect to redis server '%s': %s", addr.Host, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if addr.User != nil {
|
|
||||||
pwd, set := addr.User.Password()
|
|
||||||
if set && pwd != "" {
|
|
||||||
c.Write([]byte(fmt.Sprintf("AUTH %s\r\n", pwd)))
|
|
||||||
|
|
||||||
rdr := bufio.NewReader(c)
|
|
||||||
|
|
||||||
line, err := rdr.ReadString('\n')
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if line[0] != '+' {
|
|
||||||
return fmt.Errorf("%s", strings.TrimSpace(line)[1:])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r.c = c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r.c.Write([]byte("info\r\n"))
|
c, err := net.Dial("tcp", addr.Host)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to connect to redis server '%s': %s", addr.Host, err)
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
|
||||||
rdr := bufio.NewReader(r.c)
|
if addr.User != nil {
|
||||||
|
pwd, set := addr.User.Password()
|
||||||
|
if set && pwd != "" {
|
||||||
|
c.Write([]byte(fmt.Sprintf("AUTH %s\r\n", pwd)))
|
||||||
|
|
||||||
|
rdr := bufio.NewReader(c)
|
||||||
|
|
||||||
|
line, err := rdr.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if line[0] != '+' {
|
||||||
|
return fmt.Errorf("%s", strings.TrimSpace(line)[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Write([]byte("info\r\n"))
|
||||||
|
|
||||||
|
rdr := bufio.NewReader(c)
|
||||||
|
|
||||||
line, err := rdr.ReadString('\n')
|
line, err := rdr.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,6 +4,7 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -48,9 +49,13 @@ func CgroupCPU(containerid string, base string) (*cpu.CPUTimesStat, error) {
|
||||||
if len(base) == 0 {
|
if len(base) == 0 {
|
||||||
base = "/sys/fs/cgroup/cpuacct/docker"
|
base = "/sys/fs/cgroup/cpuacct/docker"
|
||||||
}
|
}
|
||||||
path := path.Join(base, containerid, "cpuacct.stat")
|
statfile := path.Join(base, containerid, "cpuacct.stat")
|
||||||
|
|
||||||
lines, err := common.ReadLines(path)
|
if _, err := os.Stat(statfile); os.IsNotExist(err) {
|
||||||
|
statfile = path.Join("/sys/fs/cgroup/cpuacct/system.slice", "docker-" + containerid + ".scope", "cpuacct.stat")
|
||||||
|
}
|
||||||
|
|
||||||
|
lines, err := common.ReadLines(statfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -86,12 +91,17 @@ func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
|
||||||
if len(base) == 0 {
|
if len(base) == 0 {
|
||||||
base = "/sys/fs/cgroup/memory/docker"
|
base = "/sys/fs/cgroup/memory/docker"
|
||||||
}
|
}
|
||||||
path := path.Join(base, containerid, "memory.stat")
|
statfile := path.Join(base, containerid, "memory.stat")
|
||||||
|
|
||||||
|
if _, err := os.Stat(statfile); os.IsNotExist(err) {
|
||||||
|
statfile = path.Join("/sys/fs/cgroup/memory/system.slice", "docker-" + containerid + ".scope", "memory.stat")
|
||||||
|
}
|
||||||
|
|
||||||
// empty containerid means all cgroup
|
// empty containerid means all cgroup
|
||||||
if len(containerid) == 0 {
|
if len(containerid) == 0 {
|
||||||
containerid = "all"
|
containerid = "all"
|
||||||
}
|
}
|
||||||
lines, err := common.ReadLines(path)
|
lines, err := common.ReadLines(statfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/influxdb/telegraf/plugins/system/ps/common"
|
"github.com/shirou/gopsutil/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
|
@ -26,7 +26,7 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
// skip first line
|
// skip first line
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if common.StringContains(exists, values[0]) {
|
if common.StringsHas(exists, values[0]) {
|
||||||
// skip if already get
|
// skip if already get
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -38,11 +38,14 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
base = 0
|
base = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
parsed := make([]uint64, 0, 3)
|
parsed := make([]uint64, 0, 6)
|
||||||
vv := []string{
|
vv := []string{
|
||||||
values[base+3], // PacketsRecv
|
values[base+3], // Ipkts == PacketsRecv
|
||||||
values[base+4], // Errin
|
values[base+4], // Ierrs == Errin
|
||||||
values[base+5], // Dropin
|
values[base+5], // Ibytes == BytesRecv
|
||||||
|
values[base+6], // Opkts == PacketsSent
|
||||||
|
values[base+7], // Oerrs == Errout
|
||||||
|
values[base+8], // Obytes == BytesSent
|
||||||
}
|
}
|
||||||
for _, target := range vv {
|
for _, target := range vv {
|
||||||
if target == "-" {
|
if target == "-" {
|
||||||
|
@ -61,7 +64,10 @@ func NetIOCounters(pernic bool) ([]NetIOCountersStat, error) {
|
||||||
Name: values[0],
|
Name: values[0],
|
||||||
PacketsRecv: parsed[0],
|
PacketsRecv: parsed[0],
|
||||||
Errin: parsed[1],
|
Errin: parsed[1],
|
||||||
Dropin: parsed[2],
|
BytesRecv: parsed[2],
|
||||||
|
PacketsSent: parsed[3],
|
||||||
|
Errout: parsed[4],
|
||||||
|
BytesSent: parsed[5],
|
||||||
}
|
}
|
||||||
ret = append(ret, n)
|
ret = append(ret, n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ VAGRANTFILE_API_VERSION = "2"
|
||||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
|
|
||||||
config.vm.box = "ubuntu/trusty64"
|
config.vm.box = "ubuntu/trusty64"
|
||||||
config.vm.synced_folder ".", "/home/vagrant/go/src/github.com/influxdb/telegraf",
|
config.vm.synced_folder "..", "/home/vagrant/go/src/github.com/influxdb/telegraf",
|
||||||
type: "rsync",
|
type: "rsync",
|
||||||
rsync__args: ["--verbose", "--archive", "--delete", "-z", "--safe-links"],
|
rsync__args: ["--verbose", "--archive", "--delete", "-z", "--safe-links"],
|
||||||
rsync__exclude: ["./telegraf", ".vagrant/"]
|
rsync__exclude: ["./telegraf", ".vagrant/"]
|
|
@ -39,6 +39,7 @@ LOGROTATE_DIR=/etc/logrotate.d
|
||||||
SAMPLE_CONFIGURATION=etc/config.sample.toml
|
SAMPLE_CONFIGURATION=etc/config.sample.toml
|
||||||
LOGROTATE_CONFIGURATION=etc/logrotate.d/telegraf
|
LOGROTATE_CONFIGURATION=etc/logrotate.d/telegraf
|
||||||
INITD_SCRIPT=scripts/init.sh
|
INITD_SCRIPT=scripts/init.sh
|
||||||
|
SYSTEMD_SCRIPT=scripts/telegraf.service
|
||||||
|
|
||||||
TMP_WORK_DIR=`mktemp -d`
|
TMP_WORK_DIR=`mktemp -d`
|
||||||
POST_INSTALL_PATH=`mktemp`
|
POST_INSTALL_PATH=`mktemp`
|
||||||
|
@ -49,7 +50,7 @@ MAINTAINER=support@influxdb.com
|
||||||
VENDOR=InfluxDB
|
VENDOR=InfluxDB
|
||||||
DESCRIPTION="InfluxDB Telegraf agent"
|
DESCRIPTION="InfluxDB Telegraf agent"
|
||||||
PKG_DEPS=(coreutils)
|
PKG_DEPS=(coreutils)
|
||||||
GO_VERSION="go1.4.2"
|
GO_VERSION="go1.5"
|
||||||
GOPATH_INSTALL=
|
GOPATH_INSTALL=
|
||||||
BINS=(
|
BINS=(
|
||||||
telegraf
|
telegraf
|
||||||
|
@ -156,27 +157,41 @@ generate_postinstall_script() {
|
||||||
cat <<EOF >$POST_INSTALL_PATH
|
cat <<EOF >$POST_INSTALL_PATH
|
||||||
rm -f $INSTALL_ROOT_DIR/telegraf
|
rm -f $INSTALL_ROOT_DIR/telegraf
|
||||||
rm -f $INSTALL_ROOT_DIR/init.sh
|
rm -f $INSTALL_ROOT_DIR/init.sh
|
||||||
ln -s $INSTALL_ROOT_DIR/versions/$version/telegraf $INSTALL_ROOT_DIR/telegraf
|
ln -sfn $INSTALL_ROOT_DIR/versions/$version/telegraf $INSTALL_ROOT_DIR/telegraf
|
||||||
ln -s $INSTALL_ROOT_DIR/versions/$version/scripts/init.sh $INSTALL_ROOT_DIR/init.sh
|
|
||||||
|
|
||||||
rm -f /etc/init.d/telegraf
|
|
||||||
ln -sfn $INSTALL_ROOT_DIR/init.sh /etc/init.d/telegraf
|
|
||||||
chmod +x /etc/init.d/telegraf
|
|
||||||
if which update-rc.d > /dev/null 2>&1 ; then
|
|
||||||
update-rc.d -f telegraf remove
|
|
||||||
update-rc.d telegraf defaults
|
|
||||||
else
|
|
||||||
chkconfig --add telegraf
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! id telegraf >/dev/null 2>&1; then
|
if ! id telegraf >/dev/null 2>&1; then
|
||||||
useradd --system -U -M telegraf
|
useradd --system -U -M telegraf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Systemd
|
||||||
|
if which systemctl > /dev/null 2>&1 ; then
|
||||||
|
cp $INSTALL_ROOT_DIR/versions/$version/scripts/telegraf.service \
|
||||||
|
/lib/systemd/system/telegraf.service
|
||||||
|
systemctl enable telegraf
|
||||||
|
|
||||||
|
# Sysv
|
||||||
|
else
|
||||||
|
ln -sfn $INSTALL_ROOT_DIR/versions/$version/scripts/init.sh \
|
||||||
|
$INSTALL_ROOT_DIR/init.sh
|
||||||
|
rm -f /etc/init.d/telegraf
|
||||||
|
ln -sfn $INSTALL_ROOT_DIR/init.sh /etc/init.d/telegraf
|
||||||
|
chmod +x /etc/init.d/telegraf
|
||||||
|
# update-rc.d sysv service:
|
||||||
|
if which update-rc.d > /dev/null 2>&1 ; then
|
||||||
|
update-rc.d -f telegraf remove
|
||||||
|
update-rc.d telegraf defaults
|
||||||
|
# CentOS-style sysv:
|
||||||
|
else
|
||||||
|
chkconfig --add telegraf
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p $TELEGRAF_LOG_DIR
|
||||||
|
chown -R -L telegraf:telegraf $TELEGRAF_LOG_DIR
|
||||||
|
fi
|
||||||
|
|
||||||
chown -R -L telegraf:telegraf $INSTALL_ROOT_DIR
|
chown -R -L telegraf:telegraf $INSTALL_ROOT_DIR
|
||||||
chmod -R a+rX $INSTALL_ROOT_DIR
|
chmod -R a+rX $INSTALL_ROOT_DIR
|
||||||
|
|
||||||
mkdir -p $TELEGRAF_LOG_DIR
|
|
||||||
chown -R -L telegraf:telegraf $TELEGRAF_LOG_DIR
|
|
||||||
EOF
|
EOF
|
||||||
echo "Post-install script created successfully at $POST_INSTALL_PATH"
|
echo "Post-install script created successfully at $POST_INSTALL_PATH"
|
||||||
}
|
}
|
||||||
|
@ -189,7 +204,7 @@ if [ "$1" == "-h" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
VERSION=`git describe --always --tags | tr -d v`
|
VERSION=`git describe --always --tags | tr -d v`
|
||||||
|
cd `git rev-parse --show-toplevel`
|
||||||
echo -e "\nStarting package process, version: $VERSION\n"
|
echo -e "\nStarting package process, version: $VERSION\n"
|
||||||
|
|
||||||
if [ "$CIRCLE_BRANCH" == "" ]; then
|
if [ "$CIRCLE_BRANCH" == "" ]; then
|
||||||
|
@ -213,13 +228,19 @@ done
|
||||||
echo "${BINS[*]} copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION"
|
echo "${BINS[*]} copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION"
|
||||||
|
|
||||||
cp $INITD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts
|
cp $INITD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Failed to copy init.d script to packaging directory -- aborting."
|
echo "Failed to copy init.d script to packaging directory -- aborting."
|
||||||
cleanup_exit 1
|
cleanup_exit 1
|
||||||
fi
|
fi
|
||||||
echo "$INITD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts"
|
echo "$INITD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts"
|
||||||
|
|
||||||
|
cp $SYSTEMD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Failed to copy systemd file to packaging directory -- aborting."
|
||||||
|
cleanup_exit 1
|
||||||
|
fi
|
||||||
|
echo "$SYSTEMD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts"
|
||||||
|
|
||||||
cp $SAMPLE_CONFIGURATION $TMP_WORK_DIR/$CONFIG_ROOT_DIR/telegraf.conf
|
cp $SAMPLE_CONFIGURATION $TMP_WORK_DIR/$CONFIG_ROOT_DIR/telegraf.conf
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Failed to copy $SAMPLE_CONFIGURATION to packaging directory -- aborting."
|
echo "Failed to copy $SAMPLE_CONFIGURATION to packaging directory -- aborting."
|
|
@ -8,6 +8,8 @@ EnvironmentFile=-/etc/default/telegraf
|
||||||
User=telegraf
|
User=telegraf
|
||||||
ExecStart=/opt/telegraf/telegraf -config /etc/opt/telegraf/telegraf.conf $TELEGRAF_OPTS
|
ExecStart=/opt/telegraf/telegraf -config /etc/opt/telegraf/telegraf.conf $TELEGRAF_OPTS
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
KillMode=process
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
Alias=telegraf.service
|
||||||
|
|
Loading…
Reference in New Issue