Add ability to generate config from available plugins
This commit is contained in:
parent
b2c5d95737
commit
82cbc4daa2
|
@ -16,6 +16,7 @@ var fDebug = flag.Bool("debug", false, "show metrics as they're generated to std
|
||||||
var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit")
|
var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit")
|
||||||
var fConfig = flag.String("config", "", "configuration file to load")
|
var fConfig = flag.String("config", "", "configuration file to load")
|
||||||
var fVersion = flag.Bool("version", false, "display the version")
|
var fVersion = flag.Bool("version", false, "display the version")
|
||||||
|
var fSampleConfig = flag.Bool("sample-config", false, "print out full sample configuration")
|
||||||
|
|
||||||
var Version = "unreleased"
|
var Version = "unreleased"
|
||||||
|
|
||||||
|
@ -27,6 +28,11 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *fSampleConfig {
|
||||||
|
tivan.PrintSampleConfig()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
config *tivan.Config
|
config *tivan.Config
|
||||||
err error
|
err error
|
||||||
|
|
72
config.go
72
config.go
|
@ -8,6 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdb/tivan/plugins"
|
||||||
"github.com/naoina/toml"
|
"github.com/naoina/toml"
|
||||||
"github.com/naoina/toml/ast"
|
"github.com/naoina/toml/ast"
|
||||||
)
|
)
|
||||||
|
@ -113,3 +114,74 @@ func (c *Config) ListTags() string {
|
||||||
|
|
||||||
return strings.Join(tags, " ")
|
return strings.Join(tags, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hasConfig interface {
|
||||||
|
BasicConfig() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type hasDescr interface {
|
||||||
|
Description() string
|
||||||
|
}
|
||||||
|
|
||||||
|
var header = `# Tivan configuration
|
||||||
|
|
||||||
|
# Tivan is entirely plugin driven. All metrics are gathered from the
|
||||||
|
# declared plugins.
|
||||||
|
|
||||||
|
# Even if a plugin has no configuration, it must be declared in here
|
||||||
|
# to be active. Declaring a plugin means just specifying the name
|
||||||
|
# as a section with no variables.
|
||||||
|
|
||||||
|
# Configuration for influxdb server to send metrics to
|
||||||
|
# [influxdb]
|
||||||
|
# url = "http://10.20.2.4"
|
||||||
|
# username = "tivan"
|
||||||
|
# password = "metricsmetricsmetricsmetrics"
|
||||||
|
# database = "tivan"
|
||||||
|
# user_agent = "tivan"
|
||||||
|
# tags = { "dc": "us-east-1" }
|
||||||
|
|
||||||
|
# Tags can also be specified via a normal map, but only one form at a time:
|
||||||
|
|
||||||
|
# [influxdb.tags]
|
||||||
|
# dc = "us-east-1"
|
||||||
|
|
||||||
|
# PLUGINS
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func PrintSampleConfig() {
|
||||||
|
fmt.Printf(header)
|
||||||
|
|
||||||
|
var names []string
|
||||||
|
|
||||||
|
for name, _ := range plugins.Plugins {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
creator := plugins.Plugins[name]
|
||||||
|
|
||||||
|
plugin := creator()
|
||||||
|
|
||||||
|
fmt.Printf("# %s\n[%s]\n", plugin.Description(), name)
|
||||||
|
|
||||||
|
var config string
|
||||||
|
|
||||||
|
config = strings.TrimSpace(plugin.SampleConfig())
|
||||||
|
|
||||||
|
if config == "" {
|
||||||
|
fmt.Printf(" # no configuration\n\n")
|
||||||
|
} else {
|
||||||
|
fmt.Printf("\n")
|
||||||
|
lines := strings.Split(config, "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
fmt.Printf("%s\n", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,17 +14,27 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mysql struct {
|
type Mysql struct {
|
||||||
Disabled bool
|
Servers []*Server
|
||||||
Servers []*Server
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
# specify servers via a url matching:
|
||||||
|
# [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify]]
|
||||||
|
#
|
||||||
|
# If no servers are specified, then localhost is used as the host.
|
||||||
|
servers = ["localhost"]`
|
||||||
|
|
||||||
|
func (m *Mysql) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Mysql) Description() string {
|
||||||
|
return "Read metrics from one or many mysql servers"
|
||||||
}
|
}
|
||||||
|
|
||||||
var localhost = &Server{}
|
var localhost = &Server{}
|
||||||
|
|
||||||
func (m *Mysql) Gather(acc plugins.Accumulator) error {
|
func (m *Mysql) Gather(acc plugins.Accumulator) error {
|
||||||
if m.Disabled {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(m.Servers) == 0 {
|
if len(m.Servers) == 0 {
|
||||||
// if we can't get stats in this case, thats fine, don't report
|
// if we can't get stats in this case, thats fine, don't report
|
||||||
// an error.
|
// an error.
|
||||||
|
|
|
@ -17,6 +17,39 @@ type Postgresql struct {
|
||||||
Servers []*Server
|
Servers []*Server
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
# specify servers via an array of tables
|
||||||
|
[[postgresql.servers]]
|
||||||
|
|
||||||
|
# specify address via a url matching:
|
||||||
|
# postgres://[pqgotest[:password]]@localhost?sslmode=[disable|verify-ca|verify-full]
|
||||||
|
# or a simple string:
|
||||||
|
# host=localhost user=pqotest password=... sslmode=...
|
||||||
|
#
|
||||||
|
# All connection parameters are optional. By default, the host is localhost
|
||||||
|
# and the user is the currently running user. For localhost, we default
|
||||||
|
# to sslmode=disable as well.
|
||||||
|
#
|
||||||
|
|
||||||
|
address = "localhost"
|
||||||
|
|
||||||
|
# A list of databases to pull metrics about. If not specified, metrics for all
|
||||||
|
# databases are gathered.
|
||||||
|
|
||||||
|
# databases = ["app_production", "blah_testing"]
|
||||||
|
|
||||||
|
# [[postgresql.servers]]
|
||||||
|
# address = "influx@remoteserver"
|
||||||
|
`
|
||||||
|
|
||||||
|
func (p *Postgresql) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Postgresql) Description() string {
|
||||||
|
return "Read metrics from one or many postgresql servers"
|
||||||
|
}
|
||||||
|
|
||||||
var localhost = &Server{Address: "sslmode=disable"}
|
var localhost = &Server{Address: "sslmode=disable"}
|
||||||
|
|
||||||
func (p *Postgresql) Gather(acc plugins.Accumulator) error {
|
func (p *Postgresql) Gather(acc plugins.Accumulator) error {
|
||||||
|
|
|
@ -13,14 +13,27 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Redis struct {
|
type Redis struct {
|
||||||
Disabled bool
|
Servers []string
|
||||||
Address string
|
|
||||||
Servers []string
|
|
||||||
|
|
||||||
c net.Conn
|
c net.Conn
|
||||||
buf []byte
|
buf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sampleConfig = `
|
||||||
|
# An array of address to gather stats about. Specify an ip on hostname
|
||||||
|
# with optional port. ie localhost, 10.10.3.33:18832, etc.
|
||||||
|
#
|
||||||
|
# If no servers are specified, then localhost is used as the host.
|
||||||
|
servers = ["localhost"]`
|
||||||
|
|
||||||
|
func (r *Redis) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Redis) Description() string {
|
||||||
|
return "Read metrics from one or many redis servers"
|
||||||
|
}
|
||||||
|
|
||||||
var Tracking = map[string]string{
|
var Tracking = map[string]string{
|
||||||
"uptime_in_seconds": "uptime",
|
"uptime_in_seconds": "uptime",
|
||||||
"connected_clients": "clients",
|
"connected_clients": "clients",
|
||||||
|
@ -59,19 +72,7 @@ var ErrProtocolError = errors.New("redis protocol error")
|
||||||
// Reads stats from all configured servers accumulates stats.
|
// Reads stats from all configured servers accumulates stats.
|
||||||
// Returns one of the errors encountered while gather stats (if any).
|
// Returns one of the errors encountered while gather stats (if any).
|
||||||
func (g *Redis) Gather(acc plugins.Accumulator) error {
|
func (g *Redis) Gather(acc plugins.Accumulator) error {
|
||||||
if g.Disabled {
|
if len(g.Servers) == 0 {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var servers []string
|
|
||||||
|
|
||||||
if g.Address != "" {
|
|
||||||
servers = append(servers, g.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
servers = append(servers, g.Servers...)
|
|
||||||
|
|
||||||
if len(servers) == 0 {
|
|
||||||
g.gatherServer(":6379", acc)
|
g.gatherServer(":6379", acc)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -80,7 +81,7 @@ func (g *Redis) Gather(acc plugins.Accumulator) error {
|
||||||
|
|
||||||
var outerr error
|
var outerr error
|
||||||
|
|
||||||
for _, serv := range servers {
|
for _, serv := range g.Servers {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(serv string) {
|
go func(serv string) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
|
@ -5,6 +5,8 @@ type Accumulator interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Plugin interface {
|
type Plugin interface {
|
||||||
|
SampleConfig() string
|
||||||
|
Description() string
|
||||||
Gather(Accumulator) error
|
Gather(Accumulator) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,12 @@ type CPUStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *CPUStats) Description() string {
|
||||||
|
return "Read metrics about cpu usage"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *CPUStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *CPUStats) Gather(acc plugins.Accumulator) error {
|
func (s *CPUStats) Gather(acc plugins.Accumulator) error {
|
||||||
times, err := s.ps.CPUTimes()
|
times, err := s.ps.CPUTimes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -77,6 +83,12 @@ type DiskStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *DiskStats) Description() string {
|
||||||
|
return "Read metrics about disk usage by mount point"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *DiskStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *DiskStats) Gather(acc plugins.Accumulator) error {
|
func (s *DiskStats) Gather(acc plugins.Accumulator) error {
|
||||||
disks, err := s.ps.DiskUsage()
|
disks, err := s.ps.DiskUsage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -103,6 +115,12 @@ type DiskIOStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *DiskIOStats) Description() string {
|
||||||
|
return "Read metrics about disk IO by device"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *DiskIOStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *DiskIOStats) Gather(acc plugins.Accumulator) error {
|
func (s *DiskIOStats) Gather(acc plugins.Accumulator) error {
|
||||||
diskio, err := s.ps.DiskIO()
|
diskio, err := s.ps.DiskIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -131,6 +149,12 @@ type NetIOStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *NetIOStats) Description() string {
|
||||||
|
return "Read metrics about network interface usage"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *NetIOStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *NetIOStats) Gather(acc plugins.Accumulator) error {
|
func (s *NetIOStats) Gather(acc plugins.Accumulator) error {
|
||||||
netio, err := s.ps.NetIO()
|
netio, err := s.ps.NetIO()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -159,6 +183,12 @@ type MemStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *MemStats) Description() string {
|
||||||
|
return "Read metrics about memory usage"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *MemStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *MemStats) Gather(acc plugins.Accumulator) error {
|
func (s *MemStats) Gather(acc plugins.Accumulator) error {
|
||||||
vm, err := s.ps.VMStat()
|
vm, err := s.ps.VMStat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -186,6 +216,12 @@ type SwapStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *SwapStats) Description() string {
|
||||||
|
return "Read metrics about swap memory usage"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *SwapStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *SwapStats) Gather(acc plugins.Accumulator) error {
|
func (s *SwapStats) Gather(acc plugins.Accumulator) error {
|
||||||
swap, err := s.ps.SwapStat()
|
swap, err := s.ps.SwapStat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -208,6 +244,12 @@ type DockerStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *DockerStats) Description() string {
|
||||||
|
return "Read metrics about docker containers"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *DockerStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *DockerStats) Gather(acc plugins.Accumulator) error {
|
func (s *DockerStats) Gather(acc plugins.Accumulator) error {
|
||||||
containers, err := s.ps.DockerStat()
|
containers, err := s.ps.DockerStat()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -271,6 +313,12 @@ type SystemStats struct {
|
||||||
ps PS
|
ps PS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_ *SystemStats) Description() string {
|
||||||
|
return "Read metrics about system load"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_ *SystemStats) SampleConfig() string { return "" }
|
||||||
|
|
||||||
func (s *SystemStats) add(acc plugins.Accumulator,
|
func (s *SystemStats) add(acc plugins.Accumulator,
|
||||||
name string, val float64, tags map[string]string) {
|
name string, val float64, tags map[string]string) {
|
||||||
if val >= 0 {
|
if val >= 0 {
|
||||||
|
|
Loading…
Reference in New Issue