Add support for couchdb 2.0+ API (#4654)

This commit is contained in:
Greg 2018-09-12 02:03:59 -06:00 committed by Daniel Nelson
parent 1aa969aabc
commit 9bd14b283f
4 changed files with 207 additions and 298 deletions

View File

@ -62,194 +62,12 @@ httpd statistics:
### Example output: ### Example output:
**Post Couchdb 2.0**
``` ```
➜ telegraf git:(master) ✗ ./telegraf --config ./config.conf --input-filter couchdb --test couchdb,server=http://couchdb22:5984/_node/_local/_stats couchdb_auth_cache_hits_value=0,httpd_request_methods_delete_value=0,couchdb_auth_cache_misses_value=0,httpd_request_methods_get_value=42,httpd_status_codes_304_value=0,httpd_status_codes_400_value=0,httpd_request_methods_head_value=0,httpd_status_codes_201_value=0,couchdb_database_reads_value=0,httpd_request_methods_copy_value=0,couchdb_request_time_max=0,httpd_status_codes_200_value=42,httpd_status_codes_301_value=0,couchdb_open_os_files_value=2,httpd_request_methods_put_value=0,httpd_request_methods_post_value=0,httpd_status_codes_202_value=0,httpd_status_codes_403_value=0,httpd_status_codes_409_value=0,couchdb_database_writes_value=0,couchdb_request_time_min=0,httpd_status_codes_412_value=0,httpd_status_codes_500_value=0,httpd_status_codes_401_value=0,httpd_status_codes_404_value=0,httpd_status_codes_405_value=0,couchdb_open_databases_value=0 1536707179000000000
* Plugin: couchdb, ```
Collection 1
> couchdb,server=http://localhost:5984/_stats couchdb_auth_cache_hits_current=0, **Pre Couchdb 2.0**
couchdb_auth_cache_hits_max=0, ```
couchdb_auth_cache_hits_mean=0, couchdb,server=http://couchdb16:5984/_stats couchdb_request_time_sum=96,httpd_status_codes_200_sum=37,httpd_status_codes_200_min=0,httpd_requests_mean=0.005,httpd_requests_min=0,couchdb_request_time_stddev=3.833,couchdb_request_time_min=1,httpd_request_methods_get_stddev=0.073,httpd_request_methods_get_min=0,httpd_status_codes_200_mean=0.005,httpd_status_codes_200_max=1,httpd_requests_sum=37,couchdb_request_time_current=96,httpd_request_methods_get_sum=37,httpd_request_methods_get_mean=0.005,httpd_request_methods_get_max=1,httpd_status_codes_200_stddev=0.073,couchdb_request_time_mean=2.595,couchdb_request_time_max=25,httpd_request_methods_get_current=37,httpd_status_codes_200_current=37,httpd_requests_current=37,httpd_requests_stddev=0.073,httpd_requests_max=1 1536707179000000000
couchdb_auth_cache_hits_min=0,
couchdb_auth_cache_hits_stddev=0,
couchdb_auth_cache_hits_sum=0,
couchdb_auth_cache_misses_current=0,
couchdb_auth_cache_misses_max=0,
couchdb_auth_cache_misses_mean=0,
couchdb_auth_cache_misses_min=0,
couchdb_auth_cache_misses_stddev=0,
couchdb_auth_cache_misses_sum=0,
couchdb_database_reads_current=0,
couchdb_database_reads_max=0,
couchdb_database_reads_mean=0,
couchdb_database_reads_min=0,
couchdb_database_reads_stddev=0,
couchdb_database_reads_sum=0,
couchdb_database_writes_current=1102,
couchdb_database_writes_max=131,
couchdb_database_writes_mean=0.116,
couchdb_database_writes_min=0,
couchdb_database_writes_stddev=3.536,
couchdb_database_writes_sum=1102,
couchdb_open_databases_current=1,
couchdb_open_databases_max=1,
couchdb_open_databases_mean=0,
couchdb_open_databases_min=0,
couchdb_open_databases_stddev=0.01,
couchdb_open_databases_sum=1,
couchdb_open_os_files_current=2,
couchdb_open_os_files_max=2,
couchdb_open_os_files_mean=0,
couchdb_open_os_files_min=0,
couchdb_open_os_files_stddev=0.02,
couchdb_open_os_files_sum=2,
couchdb_request_time_current=242.21,
couchdb_request_time_max=102,
couchdb_request_time_mean=5.767,
couchdb_request_time_min=1,
couchdb_request_time_stddev=17.369,
couchdb_request_time_sum=242.21,
httpd_bulk_requests_current=0,
httpd_bulk_requests_max=0,
httpd_bulk_requests_mean=0,
httpd_bulk_requests_min=0,
httpd_bulk_requests_stddev=0,
httpd_bulk_requests_sum=0,
httpd_clients_requesting_changes_current=0,
httpd_clients_requesting_changes_max=0,
httpd_clients_requesting_changes_mean=0,
httpd_clients_requesting_changes_min=0,
httpd_clients_requesting_changes_stddev=0,
httpd_clients_requesting_changes_sum=0,
httpd_request_methods_copy_current=0,
httpd_request_methods_copy_max=0,
httpd_request_methods_copy_mean=0,
httpd_request_methods_copy_min=0,
httpd_request_methods_copy_stddev=0,
httpd_request_methods_copy_sum=0,
httpd_request_methods_delete_current=0,
httpd_request_methods_delete_max=0,
httpd_request_methods_delete_mean=0,
httpd_request_methods_delete_min=0,
httpd_request_methods_delete_stddev=0,
httpd_request_methods_delete_sum=0,
httpd_request_methods_get_current=31,
httpd_request_methods_get_max=1,
httpd_request_methods_get_mean=0.003,
httpd_request_methods_get_min=0,
httpd_request_methods_get_stddev=0.057,
httpd_request_methods_get_sum=31,
httpd_request_methods_head_current=0,
httpd_request_methods_head_max=0,
httpd_request_methods_head_mean=0,
httpd_request_methods_head_min=0,
httpd_request_methods_head_stddev=0,
httpd_request_methods_head_sum=0,
httpd_request_methods_post_current=1102,
httpd_request_methods_post_max=131,
httpd_request_methods_post_mean=0.116,
httpd_request_methods_post_min=0,
httpd_request_methods_post_stddev=3.536,
httpd_request_methods_post_sum=1102,
httpd_request_methods_put_current=1,
httpd_request_methods_put_max=1,
httpd_request_methods_put_mean=0,
httpd_request_methods_put_min=0,
httpd_request_methods_put_stddev=0.01,
httpd_request_methods_put_sum=1,
httpd_requests_current=1133,
httpd_requests_max=130,
httpd_requests_mean=0.118,
httpd_requests_min=0,
httpd_requests_stddev=3.512,
httpd_requests_sum=1133,
httpd_status_codes_200_current=31,
httpd_status_codes_200_max=1,
httpd_status_codes_200_mean=0.003,
httpd_status_codes_200_min=0,
httpd_status_codes_200_stddev=0.057,
httpd_status_codes_200_sum=31,
httpd_status_codes_201_current=1103,
httpd_status_codes_201_max=130,
httpd_status_codes_201_mean=0.116,
httpd_status_codes_201_min=0,
httpd_status_codes_201_stddev=3.532,
httpd_status_codes_201_sum=1103,
httpd_status_codes_202_current=0,
httpd_status_codes_202_max=0,
httpd_status_codes_202_mean=0,
httpd_status_codes_202_min=0,
httpd_status_codes_202_stddev=0,
httpd_status_codes_202_sum=0,
httpd_status_codes_301_current=0,
httpd_status_codes_301_max=0,
httpd_status_codes_301_mean=0,
httpd_status_codes_301_min=0,
httpd_status_codes_301_stddev=0,
httpd_status_codes_301_sum=0,
httpd_status_codes_304_current=0,
httpd_status_codes_304_max=0,
httpd_status_codes_304_mean=0,
httpd_status_codes_304_min=0,
httpd_status_codes_304_stddev=0,
httpd_status_codes_304_sum=0,
httpd_status_codes_400_current=0,
httpd_status_codes_400_max=0,
httpd_status_codes_400_mean=0,
httpd_status_codes_400_min=0,
httpd_status_codes_400_stddev=0,
httpd_status_codes_400_sum=0,
httpd_status_codes_401_current=0,
httpd_status_codes_401_max=0,
httpd_status_codes_401_mean=0,
httpd_status_codes_401_min=0,
httpd_status_codes_401_stddev=0,
httpd_status_codes_401_sum=0,
httpd_status_codes_403_current=0,
httpd_status_codes_403_max=0,
httpd_status_codes_403_mean=0,
httpd_status_codes_403_min=0,
httpd_status_codes_403_stddev=0,
httpd_status_codes_403_sum=0,
httpd_status_codes_404_current=0,
httpd_status_codes_404_max=0,
httpd_status_codes_404_mean=0,
httpd_status_codes_404_min=0,
httpd_status_codes_404_stddev=0,
httpd_status_codes_404_sum=0,
httpd_status_codes_405_current=0,
httpd_status_codes_405_max=0,
httpd_status_codes_405_mean=0,
httpd_status_codes_405_min=0,
httpd_status_codes_405_stddev=0,
httpd_status_codes_405_sum=0,
httpd_status_codes_409_current=0,
httpd_status_codes_409_max=0,
httpd_status_codes_409_mean=0,
httpd_status_codes_409_min=0,
httpd_status_codes_409_stddev=0,
httpd_status_codes_409_sum=0,
httpd_status_codes_412_current=0,
httpd_status_codes_412_max=0,
httpd_status_codes_412_mean=0,
httpd_status_codes_412_min=0,
httpd_status_codes_412_stddev=0,
httpd_status_codes_412_sum=0,
httpd_status_codes_500_current=0,
httpd_status_codes_500_max=0,
httpd_status_codes_500_mean=0,
httpd_status_codes_500_min=0,
httpd_status_codes_500_stddev=0,
httpd_status_codes_500_sum=0,
httpd_temporary_view_reads_current=0,
httpd_temporary_view_reads_max=0,
httpd_temporary_view_reads_mean=0,
httpd_temporary_view_reads_min=0,
httpd_temporary_view_reads_stddev=0,
httpd_temporary_view_reads_sum=0,
httpd_view_reads_current=0,
httpd_view_reads_max=0,
httpd_view_reads_mean=0,
httpd_view_reads_min=0,
httpd_view_reads_stddev=0,
httpd_view_reads_sum=0 1454692257621938169
``` ```

View File

@ -3,44 +3,52 @@ package couchdb
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"net/http" "net/http"
"reflect"
"sync" "sync"
"time" "time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
) )
// Schema: type (
type metaData struct { metaData struct {
Description string `json:"description"` Current *float64 `json:"current"`
Current float64 `json:"current"` Sum *float64 `json:"sum"`
Sum float64 `json:"sum"` Mean *float64 `json:"mean"`
Mean float64 `json:"mean"` Stddev *float64 `json:"stddev"`
Stddev float64 `json:"stddev"` Min *float64 `json:"min"`
Min float64 `json:"min"` Max *float64 `json:"max"`
Max float64 `json:"max"` Value *float64 `json:"value"`
} }
type Stats struct { oldValue struct {
Couchdb struct { Value metaData `json:"value"`
metaData
}
couchdb struct {
AuthCacheHits metaData `json:"auth_cache_hits"`
AuthCacheMisses metaData `json:"auth_cache_misses"` AuthCacheMisses metaData `json:"auth_cache_misses"`
DatabaseWrites metaData `json:"database_writes"` DatabaseWrites metaData `json:"database_writes"`
OpenDatabases metaData `json:"open_databases"`
AuthCacheHits metaData `json:"auth_cache_hits"`
RequestTime metaData `json:"request_time"`
DatabaseReads metaData `json:"database_reads"` DatabaseReads metaData `json:"database_reads"`
OpenDatabases metaData `json:"open_databases"`
OpenOsFiles metaData `json:"open_os_files"` OpenOsFiles metaData `json:"open_os_files"`
} `json:"couchdb"` RequestTime oldValue `json:"request_time"`
HttpdRequestMethods struct { HttpdRequestMethods httpdRequestMethods `json:"httpd_request_methods"`
HttpdStatusCodes httpdStatusCodes `json:"httpd_status_codes"`
}
httpdRequestMethods struct {
Put metaData `json:"PUT"` Put metaData `json:"PUT"`
Get metaData `json:"GET"` Get metaData `json:"GET"`
Copy metaData `json:"COPY"` Copy metaData `json:"COPY"`
Delete metaData `json:"DELETE"` Delete metaData `json:"DELETE"`
Post metaData `json:"POST"` Post metaData `json:"POST"`
Head metaData `json:"HEAD"` Head metaData `json:"HEAD"`
} `json:"httpd_request_methods"` }
HttpdStatusCodes struct {
httpdStatusCodes struct {
Status200 metaData `json:"200"` Status200 metaData `json:"200"`
Status201 metaData `json:"201"` Status201 metaData `json:"201"`
Status202 metaData `json:"202"` Status202 metaData `json:"202"`
@ -54,20 +62,30 @@ type Stats struct {
Status409 metaData `json:"409"` Status409 metaData `json:"409"`
Status412 metaData `json:"412"` Status412 metaData `json:"412"`
Status500 metaData `json:"500"` Status500 metaData `json:"500"`
} `json:"httpd_status_codes"`
Httpd struct {
ClientsRequestingChanges metaData `json:"clients_requesting_changes"`
TemporaryViewReads metaData `json:"temporary_view_reads"`
Requests metaData `json:"requests"`
BulkRequests metaData `json:"bulk_requests"`
ViewReads metaData `json:"view_reads"`
} `json:"httpd"`
} }
type CouchDB struct { httpd struct {
HOSTs []string `toml:"hosts"` BulkRequests metaData `json:"bulk_requests"`
Requests metaData `json:"requests"`
TemporaryViewReads metaData `json:"temporary_view_reads"`
ViewReads metaData `json:"view_reads"`
ClientsRequestingChanges metaData `json:"clients_requesting_changes"`
} }
Stats struct {
Couchdb couchdb `json:"couchdb"`
HttpdRequestMethods httpdRequestMethods `json:"httpd_request_methods"`
HttpdStatusCodes httpdStatusCodes `json:"httpd_status_codes"`
Httpd httpd `json:"httpd"`
}
CouchDB struct {
Hosts []string `toml:"hosts"`
client *http.Client
}
)
func (*CouchDB) Description() string { func (*CouchDB) Description() string {
return "Read CouchDB Stats from one or more servers" return "Read CouchDB Stats from one or more servers"
} }
@ -75,14 +93,14 @@ func (*CouchDB) Description() string {
func (*CouchDB) SampleConfig() string { func (*CouchDB) SampleConfig() string {
return ` return `
## Works with CouchDB stats endpoints out of the box ## Works with CouchDB stats endpoints out of the box
## Multiple HOSTs from which to read CouchDB stats: ## Multiple Hosts from which to read CouchDB stats:
hosts = ["http://localhost:8086/_stats"] hosts = ["http://localhost:8086/_stats"]
` `
} }
func (c *CouchDB) Gather(accumulator telegraf.Accumulator) error { func (c *CouchDB) Gather(accumulator telegraf.Accumulator) error {
var wg sync.WaitGroup var wg sync.WaitGroup
for _, u := range c.HOSTs { for _, u := range c.Hosts {
wg.Add(1) wg.Add(1)
go func(host string) { go func(host string) {
defer wg.Done() defer wg.Done()
@ -97,67 +115,125 @@ func (c *CouchDB) Gather(accumulator telegraf.Accumulator) error {
return nil return nil
} }
var tr = &http.Transport{ func (c *CouchDB) fetchAndInsertData(accumulator telegraf.Accumulator, host string) error {
if c.client == nil {
c.client = &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: time.Duration(3 * time.Second), ResponseHeaderTimeout: time.Duration(3 * time.Second),
} },
var client = &http.Client{
Transport: tr,
Timeout: time.Duration(4 * time.Second), Timeout: time.Duration(4 * time.Second),
} }
}
func (c *CouchDB) fetchAndInsertData(accumulator telegraf.Accumulator, host string) error { response, error := c.client.Get(host)
response, error := client.Get(host)
if error != nil { if error != nil {
return error return error
} }
defer response.Body.Close() defer response.Body.Close()
var stats Stats if response.StatusCode != 200 {
return fmt.Errorf("Failed to get stats from couchdb: HTTP responded %d", response.StatusCode)
}
stats := Stats{}
decoder := json.NewDecoder(response.Body) decoder := json.NewDecoder(response.Body)
decoder.Decode(&stats) decoder.Decode(&stats)
fields := map[string]interface{}{} fields := map[string]interface{}{}
// for couchdb 2.0 API changes
requestTime := metaData{
Current: stats.Couchdb.RequestTime.Current,
Sum: stats.Couchdb.RequestTime.Sum,
Mean: stats.Couchdb.RequestTime.Mean,
Stddev: stats.Couchdb.RequestTime.Stddev,
Min: stats.Couchdb.RequestTime.Min,
Max: stats.Couchdb.RequestTime.Max,
}
httpdRequestMethodsPut := stats.HttpdRequestMethods.Put
httpdRequestMethodsGet := stats.HttpdRequestMethods.Get
httpdRequestMethodsCopy := stats.HttpdRequestMethods.Copy
httpdRequestMethodsDelete := stats.HttpdRequestMethods.Delete
httpdRequestMethodsPost := stats.HttpdRequestMethods.Post
httpdRequestMethodsHead := stats.HttpdRequestMethods.Head
httpdStatusCodesStatus200 := stats.HttpdStatusCodes.Status200
httpdStatusCodesStatus201 := stats.HttpdStatusCodes.Status201
httpdStatusCodesStatus202 := stats.HttpdStatusCodes.Status202
httpdStatusCodesStatus301 := stats.HttpdStatusCodes.Status301
httpdStatusCodesStatus304 := stats.HttpdStatusCodes.Status304
httpdStatusCodesStatus400 := stats.HttpdStatusCodes.Status400
httpdStatusCodesStatus401 := stats.HttpdStatusCodes.Status401
httpdStatusCodesStatus403 := stats.HttpdStatusCodes.Status403
httpdStatusCodesStatus404 := stats.HttpdStatusCodes.Status404
httpdStatusCodesStatus405 := stats.HttpdStatusCodes.Status405
httpdStatusCodesStatus409 := stats.HttpdStatusCodes.Status409
httpdStatusCodesStatus412 := stats.HttpdStatusCodes.Status412
httpdStatusCodesStatus500 := stats.HttpdStatusCodes.Status500
// check if couchdb2.0 is used
if stats.Couchdb.HttpdRequestMethods.Get.Value != nil {
requestTime = stats.Couchdb.RequestTime.Value
httpdRequestMethodsPut = stats.Couchdb.HttpdRequestMethods.Put
httpdRequestMethodsGet = stats.Couchdb.HttpdRequestMethods.Get
httpdRequestMethodsCopy = stats.Couchdb.HttpdRequestMethods.Copy
httpdRequestMethodsDelete = stats.Couchdb.HttpdRequestMethods.Delete
httpdRequestMethodsPost = stats.Couchdb.HttpdRequestMethods.Post
httpdRequestMethodsHead = stats.Couchdb.HttpdRequestMethods.Head
httpdStatusCodesStatus200 = stats.Couchdb.HttpdStatusCodes.Status200
httpdStatusCodesStatus201 = stats.Couchdb.HttpdStatusCodes.Status201
httpdStatusCodesStatus202 = stats.Couchdb.HttpdStatusCodes.Status202
httpdStatusCodesStatus301 = stats.Couchdb.HttpdStatusCodes.Status301
httpdStatusCodesStatus304 = stats.Couchdb.HttpdStatusCodes.Status304
httpdStatusCodesStatus400 = stats.Couchdb.HttpdStatusCodes.Status400
httpdStatusCodesStatus401 = stats.Couchdb.HttpdStatusCodes.Status401
httpdStatusCodesStatus403 = stats.Couchdb.HttpdStatusCodes.Status403
httpdStatusCodesStatus404 = stats.Couchdb.HttpdStatusCodes.Status404
httpdStatusCodesStatus405 = stats.Couchdb.HttpdStatusCodes.Status405
httpdStatusCodesStatus409 = stats.Couchdb.HttpdStatusCodes.Status409
httpdStatusCodesStatus412 = stats.Couchdb.HttpdStatusCodes.Status412
httpdStatusCodesStatus500 = stats.Couchdb.HttpdStatusCodes.Status500
}
// CouchDB meta stats: // CouchDB meta stats:
c.MapCopy(fields, c.generateFields("couchdb_auth_cache_misses", stats.Couchdb.AuthCacheMisses)) c.generateFields(fields, "couchdb_auth_cache_misses", stats.Couchdb.AuthCacheMisses)
c.MapCopy(fields, c.generateFields("couchdb_database_writes", stats.Couchdb.DatabaseWrites)) c.generateFields(fields, "couchdb_database_writes", stats.Couchdb.DatabaseWrites)
c.MapCopy(fields, c.generateFields("couchdb_open_databases", stats.Couchdb.OpenDatabases)) c.generateFields(fields, "couchdb_open_databases", stats.Couchdb.OpenDatabases)
c.MapCopy(fields, c.generateFields("couchdb_auth_cache_hits", stats.Couchdb.AuthCacheHits)) c.generateFields(fields, "couchdb_auth_cache_hits", stats.Couchdb.AuthCacheHits)
c.MapCopy(fields, c.generateFields("couchdb_request_time", stats.Couchdb.RequestTime)) c.generateFields(fields, "couchdb_request_time", requestTime)
c.MapCopy(fields, c.generateFields("couchdb_database_reads", stats.Couchdb.DatabaseReads)) c.generateFields(fields, "couchdb_database_reads", stats.Couchdb.DatabaseReads)
c.MapCopy(fields, c.generateFields("couchdb_open_os_files", stats.Couchdb.OpenOsFiles)) c.generateFields(fields, "couchdb_open_os_files", stats.Couchdb.OpenOsFiles)
// http request methods stats: // http request methods stats:
c.MapCopy(fields, c.generateFields("httpd_request_methods_put", stats.HttpdRequestMethods.Put)) c.generateFields(fields, "httpd_request_methods_put", httpdRequestMethodsPut)
c.MapCopy(fields, c.generateFields("httpd_request_methods_get", stats.HttpdRequestMethods.Get)) c.generateFields(fields, "httpd_request_methods_get", httpdRequestMethodsGet)
c.MapCopy(fields, c.generateFields("httpd_request_methods_copy", stats.HttpdRequestMethods.Copy)) c.generateFields(fields, "httpd_request_methods_copy", httpdRequestMethodsCopy)
c.MapCopy(fields, c.generateFields("httpd_request_methods_delete", stats.HttpdRequestMethods.Delete)) c.generateFields(fields, "httpd_request_methods_delete", httpdRequestMethodsDelete)
c.MapCopy(fields, c.generateFields("httpd_request_methods_post", stats.HttpdRequestMethods.Post)) c.generateFields(fields, "httpd_request_methods_post", httpdRequestMethodsPost)
c.MapCopy(fields, c.generateFields("httpd_request_methods_head", stats.HttpdRequestMethods.Head)) c.generateFields(fields, "httpd_request_methods_head", httpdRequestMethodsHead)
// status code stats: // status code stats:
c.MapCopy(fields, c.generateFields("httpd_status_codes_200", stats.HttpdStatusCodes.Status200)) c.generateFields(fields, "httpd_status_codes_200", httpdStatusCodesStatus200)
c.MapCopy(fields, c.generateFields("httpd_status_codes_201", stats.HttpdStatusCodes.Status201)) c.generateFields(fields, "httpd_status_codes_201", httpdStatusCodesStatus201)
c.MapCopy(fields, c.generateFields("httpd_status_codes_202", stats.HttpdStatusCodes.Status202)) c.generateFields(fields, "httpd_status_codes_202", httpdStatusCodesStatus202)
c.MapCopy(fields, c.generateFields("httpd_status_codes_301", stats.HttpdStatusCodes.Status301)) c.generateFields(fields, "httpd_status_codes_301", httpdStatusCodesStatus301)
c.MapCopy(fields, c.generateFields("httpd_status_codes_304", stats.HttpdStatusCodes.Status304)) c.generateFields(fields, "httpd_status_codes_304", httpdStatusCodesStatus304)
c.MapCopy(fields, c.generateFields("httpd_status_codes_400", stats.HttpdStatusCodes.Status400)) c.generateFields(fields, "httpd_status_codes_400", httpdStatusCodesStatus400)
c.MapCopy(fields, c.generateFields("httpd_status_codes_401", stats.HttpdStatusCodes.Status401)) c.generateFields(fields, "httpd_status_codes_401", httpdStatusCodesStatus401)
c.MapCopy(fields, c.generateFields("httpd_status_codes_403", stats.HttpdStatusCodes.Status403)) c.generateFields(fields, "httpd_status_codes_403", httpdStatusCodesStatus403)
c.MapCopy(fields, c.generateFields("httpd_status_codes_404", stats.HttpdStatusCodes.Status404)) c.generateFields(fields, "httpd_status_codes_404", httpdStatusCodesStatus404)
c.MapCopy(fields, c.generateFields("httpd_status_codes_405", stats.HttpdStatusCodes.Status405)) c.generateFields(fields, "httpd_status_codes_405", httpdStatusCodesStatus405)
c.MapCopy(fields, c.generateFields("httpd_status_codes_409", stats.HttpdStatusCodes.Status409)) c.generateFields(fields, "httpd_status_codes_409", httpdStatusCodesStatus409)
c.MapCopy(fields, c.generateFields("httpd_status_codes_412", stats.HttpdStatusCodes.Status412)) c.generateFields(fields, "httpd_status_codes_412", httpdStatusCodesStatus412)
c.MapCopy(fields, c.generateFields("httpd_status_codes_500", stats.HttpdStatusCodes.Status500)) c.generateFields(fields, "httpd_status_codes_500", httpdStatusCodesStatus500)
// httpd stats: // httpd stats:
c.MapCopy(fields, c.generateFields("httpd_clients_requesting_changes", stats.Httpd.ClientsRequestingChanges)) c.generateFields(fields, "httpd_clients_requesting_changes", stats.Httpd.ClientsRequestingChanges)
c.MapCopy(fields, c.generateFields("httpd_temporary_view_reads", stats.Httpd.TemporaryViewReads)) c.generateFields(fields, "httpd_temporary_view_reads", stats.Httpd.TemporaryViewReads)
c.MapCopy(fields, c.generateFields("httpd_requests", stats.Httpd.Requests)) c.generateFields(fields, "httpd_requests", stats.Httpd.Requests)
c.MapCopy(fields, c.generateFields("httpd_bulk_requests", stats.Httpd.BulkRequests)) c.generateFields(fields, "httpd_bulk_requests", stats.Httpd.BulkRequests)
c.MapCopy(fields, c.generateFields("httpd_view_reads", stats.Httpd.ViewReads)) c.generateFields(fields, "httpd_view_reads", stats.Httpd.ViewReads)
tags := map[string]string{ tags := map[string]string{
"server": host, "server": host,
@ -166,34 +242,39 @@ func (c *CouchDB) fetchAndInsertData(accumulator telegraf.Accumulator, host stri
return nil return nil
} }
func (*CouchDB) MapCopy(dst, src interface{}) { func (c *CouchDB) generateFields(fields map[string]interface{}, prefix string, obj metaData) {
dv, sv := reflect.ValueOf(dst), reflect.ValueOf(src) if obj.Value != nil {
for _, k := range sv.MapKeys() { fields[prefix+"_value"] = *obj.Value
dv.SetMapIndex(k, sv.MapIndex(k))
} }
if obj.Current != nil {
fields[prefix+"_current"] = *obj.Current
} }
if obj.Sum != nil {
func (*CouchDB) safeCheck(value interface{}) interface{} { fields[prefix+"_sum"] = *obj.Sum
if value == nil {
return 0.0
} }
return value if obj.Mean != nil {
fields[prefix+"_mean"] = *obj.Mean
} }
if obj.Stddev != nil {
func (c *CouchDB) generateFields(prefix string, obj metaData) map[string]interface{} { fields[prefix+"_stddev"] = *obj.Stddev
fields := map[string]interface{}{ }
prefix + "_current": c.safeCheck(obj.Current), if obj.Min != nil {
prefix + "_sum": c.safeCheck(obj.Sum), fields[prefix+"_min"] = *obj.Min
prefix + "_mean": c.safeCheck(obj.Mean), }
prefix + "_stddev": c.safeCheck(obj.Stddev), if obj.Max != nil {
prefix + "_min": c.safeCheck(obj.Min), fields[prefix+"_max"] = *obj.Max
prefix + "_max": c.safeCheck(obj.Max),
} }
return fields
} }
func init() { func init() {
inputs.Add("couchdb", func() telegraf.Input { inputs.Add("couchdb", func() telegraf.Input {
return &CouchDB{} return &CouchDB{
client: &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: time.Duration(3 * time.Second),
},
Timeout: time.Duration(4 * time.Second),
},
}
}) })
} }

View File

@ -1,12 +1,13 @@
package couchdb_test package couchdb_test
import ( import (
"github.com/influxdata/telegraf/plugins/inputs/couchdb"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/influxdata/telegraf/plugins/inputs/couchdb"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
) )
func TestBasic(t *testing.T) { func TestBasic(t *testing.T) {
@ -312,7 +313,7 @@ func TestBasic(t *testing.T) {
defer fakeServer.Close() defer fakeServer.Close()
plugin := &couchdb.CouchDB{ plugin := &couchdb.CouchDB{
HOSTs: []string{fakeServer.URL + "/_stats"}, Hosts: []string{fakeServer.URL + "/_stats"},
} }
var acc testutil.Accumulator var acc testutil.Accumulator

View File

@ -0,0 +1,9 @@
[agent]
interval="1s"
flush_interval="1s"
[[inputs.couchdb]]
hosts = ["http://couchdb16:5984/_stats", "http://couchdb22:5984/_node/_local/_stats"]
[[outputs.file]]
files = ["stdout"]