1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,97 @@
# Apache CouchDB Input Plugin
This plugin gathers metrics from [Apache CouchDB][couchdb] instances using the
[stats][stats] endpoint.
⭐ Telegraf v0.10.3
🏷️ server
💻 all
[couchdb]: https://couchdb.apache.org/
[stats]: http://docs.couchdb.org/en/1.6.1/api/server/common.html?highlight=stats#get--_stats
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
## Configuration
```toml @sample.conf
# Read CouchDB Stats from one or more servers
[[inputs.couchdb]]
## Works with CouchDB stats endpoints out of the box
## Multiple Hosts from which to read CouchDB stats:
hosts = ["http://localhost:8086/_stats"]
## Use HTTP Basic Authentication.
# basic_username = "telegraf"
# basic_password = "p@ssw0rd"
```
## Metrics
Statistics specific to the internals of CouchDB:
- couchdb_auth_cache_misses
- couchdb_database_writes
- couchdb_open_databases
- couchdb_auth_cache_hits
- couchdb_request_time
- couchdb_database_reads
- couchdb_open_os_files
Statistics of HTTP requests by method:
- httpd_request_methods_put
- httpd_request_methods_get
- httpd_request_methods_copy
- httpd_request_methods_delete
- httpd_request_methods_post
- httpd_request_methods_head
Statistics of HTTP requests by response code:
- httpd_status_codes_200
- httpd_status_codes_201
- httpd_status_codes_202
- httpd_status_codes_301
- httpd_status_codes_304
- httpd_status_codes_400
- httpd_status_codes_401
- httpd_status_codes_403
- httpd_status_codes_404
- httpd_status_codes_405
- httpd_status_codes_409
- httpd_status_codes_412
- httpd_status_codes_500
httpd statistics:
- httpd_clients_requesting_changes
- httpd_temporary_view_reads
- httpd_requests
- httpd_bulk_requests
- httpd_view_reads
## Tags
- server (url of the couchdb _stats endpoint)
## Example Output
### Post Couchdb 2.0
```text
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
```
### Pre Couchdb 2.0
```text
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
```

View file

@ -0,0 +1,290 @@
//go:generate ../../../tools/readme_config_includer/generator
package couchdb
import (
_ "embed"
"encoding/json"
"fmt"
"net/http"
"sync"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type CouchDB struct {
Hosts []string `toml:"hosts"`
BasicUsername string `toml:"basic_username"`
BasicPassword string `toml:"basic_password"`
client *http.Client
}
type (
metaData struct {
Current *float64 `json:"current"`
Sum *float64 `json:"sum"`
Mean *float64 `json:"mean"`
Stddev *float64 `json:"stddev"`
Min *float64 `json:"min"`
Max *float64 `json:"max"`
Value *float64 `json:"value"`
}
oldValue struct {
Value metaData `json:"value"`
metaData
}
couchdb struct {
AuthCacheHits metaData `json:"auth_cache_hits"`
AuthCacheMisses metaData `json:"auth_cache_misses"`
DatabaseWrites metaData `json:"database_writes"`
DatabaseReads metaData `json:"database_reads"`
OpenDatabases metaData `json:"open_databases"`
OpenOsFiles metaData `json:"open_os_files"`
RequestTime oldValue `json:"request_time"`
HttpdRequestMethods httpdRequestMethods `json:"httpd_request_methods"`
HttpdStatusCodes httpdStatusCodes `json:"httpd_status_codes"`
}
httpdRequestMethods struct {
Put metaData `json:"PUT"`
Get metaData `json:"GET"`
Copy metaData `json:"COPY"`
Delete metaData `json:"DELETE"`
Post metaData `json:"POST"`
Head metaData `json:"HEAD"`
}
httpdStatusCodes struct {
Status200 metaData `json:"200"`
Status201 metaData `json:"201"`
Status202 metaData `json:"202"`
Status301 metaData `json:"301"`
Status304 metaData `json:"304"`
Status400 metaData `json:"400"`
Status401 metaData `json:"401"`
Status403 metaData `json:"403"`
Status404 metaData `json:"404"`
Status405 metaData `json:"405"`
Status409 metaData `json:"409"`
Status412 metaData `json:"412"`
Status500 metaData `json:"500"`
}
httpd struct {
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"`
}
)
func (*CouchDB) SampleConfig() string {
return sampleConfig
}
func (c *CouchDB) Gather(accumulator telegraf.Accumulator) error {
var wg sync.WaitGroup
for _, u := range c.Hosts {
wg.Add(1)
go func(host string) {
defer wg.Done()
if err := c.fetchAndInsertData(accumulator, host); err != nil {
accumulator.AddError(fmt.Errorf("[host=%s]: %w", host, err))
}
}(u)
}
wg.Wait()
return nil
}
func (c *CouchDB) fetchAndInsertData(accumulator telegraf.Accumulator, host string) error {
if c.client == nil {
c.client = &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: 3 * time.Second,
},
Timeout: 4 * time.Second,
}
}
req, err := http.NewRequest("GET", host, nil)
if err != nil {
return err
}
if c.BasicUsername != "" || c.BasicPassword != "" {
req.SetBasicAuth(c.BasicUsername, c.BasicPassword)
}
response, err := c.client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
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)
if err := decoder.Decode(&stats); err != nil {
return fmt.Errorf("failed to decode stats from couchdb: HTTP body %q", response.Body)
}
// 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
}
fields := make(map[string]interface{}, 31)
// CouchDB meta stats:
generateFields(fields, "couchdb_auth_cache_misses", stats.Couchdb.AuthCacheMisses)
generateFields(fields, "couchdb_database_writes", stats.Couchdb.DatabaseWrites)
generateFields(fields, "couchdb_open_databases", stats.Couchdb.OpenDatabases)
generateFields(fields, "couchdb_auth_cache_hits", stats.Couchdb.AuthCacheHits)
generateFields(fields, "couchdb_request_time", requestTime)
generateFields(fields, "couchdb_database_reads", stats.Couchdb.DatabaseReads)
generateFields(fields, "couchdb_open_os_files", stats.Couchdb.OpenOsFiles)
// http request methods stats:
generateFields(fields, "httpd_request_methods_put", httpdRequestMethodsPut)
generateFields(fields, "httpd_request_methods_get", httpdRequestMethodsGet)
generateFields(fields, "httpd_request_methods_copy", httpdRequestMethodsCopy)
generateFields(fields, "httpd_request_methods_delete", httpdRequestMethodsDelete)
generateFields(fields, "httpd_request_methods_post", httpdRequestMethodsPost)
generateFields(fields, "httpd_request_methods_head", httpdRequestMethodsHead)
// status code stats:
generateFields(fields, "httpd_status_codes_200", httpdStatusCodesStatus200)
generateFields(fields, "httpd_status_codes_201", httpdStatusCodesStatus201)
generateFields(fields, "httpd_status_codes_202", httpdStatusCodesStatus202)
generateFields(fields, "httpd_status_codes_301", httpdStatusCodesStatus301)
generateFields(fields, "httpd_status_codes_304", httpdStatusCodesStatus304)
generateFields(fields, "httpd_status_codes_400", httpdStatusCodesStatus400)
generateFields(fields, "httpd_status_codes_401", httpdStatusCodesStatus401)
generateFields(fields, "httpd_status_codes_403", httpdStatusCodesStatus403)
generateFields(fields, "httpd_status_codes_404", httpdStatusCodesStatus404)
generateFields(fields, "httpd_status_codes_405", httpdStatusCodesStatus405)
generateFields(fields, "httpd_status_codes_409", httpdStatusCodesStatus409)
generateFields(fields, "httpd_status_codes_412", httpdStatusCodesStatus412)
generateFields(fields, "httpd_status_codes_500", httpdStatusCodesStatus500)
// httpd stats:
generateFields(fields, "httpd_clients_requesting_changes", stats.Httpd.ClientsRequestingChanges)
generateFields(fields, "httpd_temporary_view_reads", stats.Httpd.TemporaryViewReads)
generateFields(fields, "httpd_requests", stats.Httpd.Requests)
generateFields(fields, "httpd_bulk_requests", stats.Httpd.BulkRequests)
generateFields(fields, "httpd_view_reads", stats.Httpd.ViewReads)
tags := map[string]string{
"server": host,
}
accumulator.AddFields("couchdb", fields, tags)
return nil
}
func generateFields(fields map[string]interface{}, prefix string, obj metaData) {
if obj.Value != nil {
fields[prefix+"_value"] = *obj.Value
}
if obj.Current != nil {
fields[prefix+"_current"] = *obj.Current
}
if obj.Sum != nil {
fields[prefix+"_sum"] = *obj.Sum
}
if obj.Mean != nil {
fields[prefix+"_mean"] = *obj.Mean
}
if obj.Stddev != nil {
fields[prefix+"_stddev"] = *obj.Stddev
}
if obj.Min != nil {
fields[prefix+"_min"] = *obj.Min
}
if obj.Max != nil {
fields[prefix+"_max"] = *obj.Max
}
}
func init() {
inputs.Add("couchdb", func() telegraf.Input {
return &CouchDB{
client: &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: 3 * time.Second,
},
Timeout: 4 * time.Second,
},
}
})
}

View file

@ -0,0 +1,326 @@
package couchdb_test
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/plugins/inputs/couchdb"
"github.com/influxdata/telegraf/testutil"
)
func TestBasic(t *testing.T) {
js := `
{
"couchdb": {
"auth_cache_misses": {
"description": "number of authentication cache misses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"database_writes": {
"description": "number of times a database was changed",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"open_databases": {
"description": "number of open databases",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"auth_cache_hits": {
"description": "number of authentication cache hits",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"request_time": {
"description": "length of a request inside CouchDB without MochiWeb",
"current": 18.0,
"sum": 18.0,
"mean": 18.0,
"stddev": null,
"min": 18.0,
"max": 18.0
},
"database_reads": {
"description": "number of times a document was read from a database",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"open_os_files": {
"description": "number of file descriptors CouchDB has open",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
}
},
"httpd_request_methods": {
"PUT": {
"description": "number of HTTP PUT requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"GET": {
"description": "number of HTTP GET requests",
"current": 2.0,
"sum": 2.0,
"mean": 0.25,
"stddev": 0.70699999999999996181,
"min": 0,
"max": 2
},
"COPY": {
"description": "number of HTTP COPY requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"DELETE": {
"description": "number of HTTP DELETE requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"POST": {
"description": "number of HTTP POST requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"HEAD": {
"description": "number of HTTP HEAD requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
}
},
"httpd_status_codes": {
"403": {
"description": "number of HTTP 403 Forbidden responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"202": {
"description": "number of HTTP 202 Accepted responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"401": {
"description": "number of HTTP 401 Unauthorized responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"409": {
"description": "number of HTTP 409 Conflict responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"200": {
"description": "number of HTTP 200 OK responses",
"current": 1.0,
"sum": 1.0,
"mean": 0.125,
"stddev": 0.35399999999999998135,
"min": 0,
"max": 1
},
"405": {
"description": "number of HTTP 405 Method Not Allowed responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"400": {
"description": "number of HTTP 400 Bad Request responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"201": {
"description": "number of HTTP 201 Created responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"404": {
"description": "number of HTTP 404 Not Found responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"500": {
"description": "number of HTTP 500 Internal Server Error responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"412": {
"description": "number of HTTP 412 Precondition Failed responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"301": {
"description": "number of HTTP 301 Moved Permanently responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"304": {
"description": "number of HTTP 304 Not Modified responses",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
}
},
"httpd": {
"clients_requesting_changes": {
"description": "number of clients for continuous _changes",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"temporary_view_reads": {
"description": "number of temporary view reads",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"requests": {
"description": "number of HTTP requests",
"current": 2.0,
"sum": 2.0,
"mean": 0.25,
"stddev": 0.70699999999999996181,
"min": 0,
"max": 2
},
"bulk_requests": {
"description": "number of bulk requests",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
},
"view_reads": {
"description": "number of view reads",
"current": null,
"sum": null,
"mean": null,
"stddev": null,
"min": null,
"max": null
}
}
}
`
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/_stats" {
if _, err := w.Write([]byte(js)); err != nil {
w.WriteHeader(http.StatusInternalServerError)
t.Error(err)
return
}
} else {
w.WriteHeader(http.StatusNotFound)
}
}))
defer fakeServer.Close()
plugin := &couchdb.CouchDB{
Hosts: []string{fakeServer.URL + "/_stats"},
}
var acc testutil.Accumulator
require.NoError(t, acc.GatherError(plugin.Gather))
}

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"]

View file

@ -0,0 +1,9 @@
# Read CouchDB Stats from one or more servers
[[inputs.couchdb]]
## Works with CouchDB stats endpoints out of the box
## Multiple Hosts from which to read CouchDB stats:
hosts = ["http://localhost:8086/_stats"]
## Use HTTP Basic Authentication.
# basic_username = "telegraf"
# basic_password = "p@ssw0rd"