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,81 @@
# Tengine Input Plugin
The tengine plugin gathers metrics from the
[Tengine Web Server](http://tengine.taobao.org/) via the
[reqstat](http://tengine.taobao.org/document/http_reqstat.html) module.
## 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 Tengine's basic status information (ngx_http_reqstat_module)
[[inputs.tengine]]
## An array of Tengine reqstat module URI to gather stats.
urls = ["http://127.0.0.1/us"]
## HTTP response timeout (default: 5s)
# response_timeout = "5s"
## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"
## Use TLS but skip chain & host verification
# insecure_skip_verify = false
```
## Metrics
- Measurement
- tags:
- port
- server
- server_name
- fields:
- bytes_in (integer, total number of bytes received from client)
- bytes_out (integer, total number of bytes sent to client)
- conn_total (integer, total number of accepted connections)
- req_total (integer, total number of processed requests)
- http_2xx (integer, total number of 2xx requests)
- http_3xx (integer, total number of 3xx requests)
- http_4xx (integer, total number of 4xx requests)
- http_5xx (integer, total number of 5xx requests)
- http_other_status (integer, total number of other requests)
- rt (integer, accumulation or rt)
- ups_req (integer, total number of requests calling for upstream)
- ups_rt (integer, accumulation or upstream rt)
- ups_tries (integer, total number of times calling for upstream)
- http_200 (integer, total number of 200 requests)
- http_206 (integer, total number of 206 requests)
- http_302 (integer, total number of 302 requests)
- http_304 (integer, total number of 304 requests)
- http_403 (integer, total number of 403 requests)
- http_404 (integer, total number of 404 requests)
- http_416 (integer, total number of 416 requests)
- http_499 (integer, total number of 499 requests)
- http_500 (integer, total number of 500 requests)
- http_502 (integer, total number of 502 requests)
- http_503 (integer, total number of 503 requests)
- http_504 (integer, total number of 504 requests)
- http_508 (integer, total number of 508 requests)
- http_other_detail_status (integer, total number of requests of other
status codes*http_ups_4xx total number of requests of upstream 4xx)
- http_ups_5xx (integer, total number of requests of upstream 5xx)
## Example Output
```text
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=localhost bytes_in=9129i,bytes_out=56334i,conn_total=14i,http_200=90i,http_206=0i,http_2xx=90i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=0i,http_416=0i,http_499=0i,http_4xx=0i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=90i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=28.79.190.35.bc.googleusercontent.com bytes_in=1500i,bytes_out=3009i,conn_total=4i,http_200=1i,http_206=0i,http_2xx=1i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=1i,http_416=0i,http_499=0i,http_4xx=3i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=4i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=www.google.com bytes_in=372i,bytes_out=786i,conn_total=1i,http_200=1i,http_206=0i,http_2xx=1i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=0i,http_416=0i,http_499=0i,http_4xx=0i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=1i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=35.190.79.28 bytes_in=4433i,bytes_out=10259i,conn_total=5i,http_200=3i,http_206=0i,http_2xx=3i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=11i,http_416=0i,http_499=0i,http_4xx=11i,http_500=0i,http_502=0i,http_503=0i,http_504=0i,http_508=0i,http_5xx=0i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=0i,http_ups_5xx=0i,req_total=14i,rt=0i,ups_req=0i,ups_rt=0i,ups_tries=0i 1526546308000000000
tengine,host=gcp-thz-api-5,port=80,server=localhost,server_name=tenka-prod-api.txwy.tw bytes_in=3014397400i,bytes_out=14279992835i,conn_total=36844i,http_200=3177339i,http_206=0i,http_2xx=3177339i,http_302=0i,http_304=0i,http_3xx=0i,http_403=0i,http_404=123i,http_416=0i,http_499=0i,http_4xx=123i,http_500=17214i,http_502=4453i,http_503=80i,http_504=0i,http_508=0i,http_5xx=21747i,http_other_detail_status=0i,http_other_status=0i,http_ups_4xx=123i,http_ups_5xx=21747i,req_total=3199209i,rt=245874536i,ups_req=2685076i,ups_rt=245858217i,ups_tries=2685076i 1526546308000000000
```

View file

@ -0,0 +1,14 @@
# Read Tengine's basic status information (ngx_http_reqstat_module)
[[inputs.tengine]]
## An array of Tengine reqstat module URI to gather stats.
urls = ["http://127.0.0.1/us"]
## HTTP response timeout (default: 5s)
# response_timeout = "5s"
## Optional TLS Config
# tls_ca = "/etc/telegraf/ca.pem"
# tls_cert = "/etc/telegraf/cert.pem"
# tls_key = "/etc/telegraf/key.pem"
## Use TLS but skip chain & host verification
# insecure_skip_verify = false

View file

@ -0,0 +1,325 @@
//go:generate ../../../tools/readme_config_includer/generator
package tengine
import (
"bufio"
_ "embed"
"errors"
"fmt"
"io"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/tls"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type Tengine struct {
Urls []string `toml:"urls"`
ResponseTimeout config.Duration `toml:"response_timeout"`
tls.ClientConfig
client *http.Client
}
type tengineStatus struct {
host string
bytesIn uint64
bytesOut uint64
connTotal uint64
reqTotal uint64
http2xx uint64
http3xx uint64
http4xx uint64
http5xx uint64
httpOtherStatus uint64
rt uint64
upsReq uint64
upsRt uint64
upsTries uint64
http200 uint64
http206 uint64
http302 uint64
http304 uint64
http403 uint64
http404 uint64
http416 uint64
http499 uint64
http500 uint64
http502 uint64
http503 uint64
http504 uint64
http508 uint64
httpOtherDetailStatus uint64
httpUps4xx uint64
httpUps5xx uint64
}
func (*Tengine) SampleConfig() string {
return sampleConfig
}
func (n *Tengine) Gather(acc telegraf.Accumulator) error {
var wg sync.WaitGroup
// Create an HTTP client that is re-used for each
// collection interval
if n.client == nil {
client, err := n.createHTTPClient()
if err != nil {
return err
}
n.client = client
}
for _, u := range n.Urls {
addr, err := url.Parse(u)
if err != nil {
acc.AddError(fmt.Errorf("unable to parse address %q: %w", u, err))
continue
}
wg.Add(1)
go func(addr *url.URL) {
defer wg.Done()
acc.AddError(n.gatherURL(addr, acc))
}(addr)
}
wg.Wait()
return nil
}
func (n *Tengine) createHTTPClient() (*http.Client, error) {
tlsCfg, err := n.ClientConfig.TLSConfig()
if err != nil {
return nil, err
}
if n.ResponseTimeout < config.Duration(time.Second) {
n.ResponseTimeout = config.Duration(time.Second * 5)
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsCfg,
},
Timeout: time.Duration(n.ResponseTimeout),
}
return client, nil
}
func (n *Tengine) gatherURL(addr *url.URL, acc telegraf.Accumulator) error {
var tStatus tengineStatus
resp, err := n.client.Get(addr.String())
if err != nil {
return fmt.Errorf("error making HTTP request to %q: %w", addr.String(), err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("%s returned HTTP status %s", addr.String(), resp.Status)
}
r := bufio.NewReader(resp.Body)
for {
line, err := r.ReadString('\n')
if err != nil || errors.Is(err, io.EOF) {
break
}
lineSplit := strings.Split(strings.TrimSpace(line), ",")
if len(lineSplit) != 30 {
continue
}
tStatus.host = lineSplit[0]
if err != nil {
return err
}
tStatus.bytesIn, err = strconv.ParseUint(lineSplit[1], 10, 64)
if err != nil {
return err
}
tStatus.bytesOut, err = strconv.ParseUint(lineSplit[2], 10, 64)
if err != nil {
return err
}
tStatus.connTotal, err = strconv.ParseUint(lineSplit[3], 10, 64)
if err != nil {
return err
}
tStatus.reqTotal, err = strconv.ParseUint(lineSplit[4], 10, 64)
if err != nil {
return err
}
tStatus.http2xx, err = strconv.ParseUint(lineSplit[5], 10, 64)
if err != nil {
return err
}
tStatus.http3xx, err = strconv.ParseUint(lineSplit[6], 10, 64)
if err != nil {
return err
}
tStatus.http4xx, err = strconv.ParseUint(lineSplit[7], 10, 64)
if err != nil {
return err
}
tStatus.http5xx, err = strconv.ParseUint(lineSplit[8], 10, 64)
if err != nil {
return err
}
tStatus.httpOtherStatus, err = strconv.ParseUint(lineSplit[9], 10, 64)
if err != nil {
return err
}
tStatus.rt, err = strconv.ParseUint(lineSplit[10], 10, 64)
if err != nil {
return err
}
tStatus.upsReq, err = strconv.ParseUint(lineSplit[11], 10, 64)
if err != nil {
return err
}
tStatus.upsRt, err = strconv.ParseUint(lineSplit[12], 10, 64)
if err != nil {
return err
}
tStatus.upsTries, err = strconv.ParseUint(lineSplit[13], 10, 64)
if err != nil {
return err
}
tStatus.http200, err = strconv.ParseUint(lineSplit[14], 10, 64)
if err != nil {
return err
}
tStatus.http206, err = strconv.ParseUint(lineSplit[15], 10, 64)
if err != nil {
return err
}
tStatus.http302, err = strconv.ParseUint(lineSplit[16], 10, 64)
if err != nil {
return err
}
tStatus.http304, err = strconv.ParseUint(lineSplit[17], 10, 64)
if err != nil {
return err
}
tStatus.http403, err = strconv.ParseUint(lineSplit[18], 10, 64)
if err != nil {
return err
}
tStatus.http404, err = strconv.ParseUint(lineSplit[19], 10, 64)
if err != nil {
return err
}
tStatus.http416, err = strconv.ParseUint(lineSplit[20], 10, 64)
if err != nil {
return err
}
tStatus.http499, err = strconv.ParseUint(lineSplit[21], 10, 64)
if err != nil {
return err
}
tStatus.http500, err = strconv.ParseUint(lineSplit[22], 10, 64)
if err != nil {
return err
}
tStatus.http502, err = strconv.ParseUint(lineSplit[23], 10, 64)
if err != nil {
return err
}
tStatus.http503, err = strconv.ParseUint(lineSplit[24], 10, 64)
if err != nil {
return err
}
tStatus.http504, err = strconv.ParseUint(lineSplit[25], 10, 64)
if err != nil {
return err
}
tStatus.http508, err = strconv.ParseUint(lineSplit[26], 10, 64)
if err != nil {
return err
}
tStatus.httpOtherDetailStatus, err = strconv.ParseUint(lineSplit[27], 10, 64)
if err != nil {
return err
}
tStatus.httpUps4xx, err = strconv.ParseUint(lineSplit[28], 10, 64)
if err != nil {
return err
}
tStatus.httpUps5xx, err = strconv.ParseUint(lineSplit[29], 10, 64)
if err != nil {
return err
}
tags := getTags(addr, tStatus.host)
fields := map[string]interface{}{
"bytes_in": tStatus.bytesIn,
"bytes_out": tStatus.bytesOut,
"conn_total": tStatus.connTotal,
"req_total": tStatus.reqTotal,
"http_2xx": tStatus.http2xx,
"http_3xx": tStatus.http3xx,
"http_4xx": tStatus.http4xx,
"http_5xx": tStatus.http5xx,
"http_other_status": tStatus.httpOtherStatus,
"rt": tStatus.rt,
"ups_req": tStatus.upsReq,
"ups_rt": tStatus.upsRt,
"ups_tries": tStatus.upsTries,
"http_200": tStatus.http200,
"http_206": tStatus.http206,
"http_302": tStatus.http302,
"http_304": tStatus.http304,
"http_403": tStatus.http403,
"http_404": tStatus.http404,
"http_416": tStatus.http416,
"http_499": tStatus.http499,
"http_500": tStatus.http500,
"http_502": tStatus.http502,
"http_503": tStatus.http503,
"http_504": tStatus.http504,
"http_508": tStatus.http508,
"http_other_detail_status": tStatus.httpOtherDetailStatus,
"http_ups_4xx": tStatus.httpUps4xx,
"http_ups_5xx": tStatus.httpUps5xx,
}
acc.AddFields("tengine", fields, tags)
}
// Return the potential error of the loop-read
return err
}
// Get tag(s) for the tengine plugin
func getTags(addr *url.URL, serverName string) map[string]string {
h := addr.Host
host, port, err := net.SplitHostPort(h)
if err != nil {
host = addr.Host
if addr.Scheme == "http" {
port = "80"
} else if addr.Scheme == "https" {
port = "443"
} else {
port = ""
}
}
return map[string]string{"server": host, "port": port, "server_name": serverName}
}
func init() {
inputs.Add("tengine", func() telegraf.Input {
return &Tengine{}
})
}

View file

@ -0,0 +1,99 @@
package tengine
import (
"fmt"
"net"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
const tengineSampleResponse = `127.0.0.1,784,1511,2,2,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0`
// Verify that tengine tags are properly parsed based on the server
func TestTengineTags(t *testing.T) {
urls := []string{"http://localhost/us", "http://localhost:80/us"}
for _, url1 := range urls {
addr, err := url.Parse(url1)
require.NoError(t, err)
tagMap := getTags(addr, "127.0.0.1")
require.Contains(t, tagMap["server"], "localhost")
}
}
func TestTengineGeneratesMetrics(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
if _, err := fmt.Fprintln(w, tengineSampleResponse); err != nil {
w.WriteHeader(http.StatusInternalServerError)
t.Error(err)
return
}
}))
defer ts.Close()
n := &Tengine{
Urls: []string{ts.URL + "/us"},
}
var accTengine testutil.Accumulator
errTengine := accTengine.GatherError(n.Gather)
require.NoError(t, errTengine)
fieldsTengine := map[string]interface{}{
"bytes_in": uint64(784),
"bytes_out": uint64(1511),
"conn_total": uint64(2),
"req_total": uint64(2),
"http_2xx": uint64(1),
"http_3xx": uint64(0),
"http_4xx": uint64(1),
"http_5xx": uint64(0),
"http_other_status": uint64(0),
"rt": uint64(0),
"ups_req": uint64(0),
"ups_rt": uint64(0),
"ups_tries": uint64(0),
"http_200": uint64(1),
"http_206": uint64(0),
"http_302": uint64(0),
"http_304": uint64(0),
"http_403": uint64(0),
"http_404": uint64(1),
"http_416": uint64(0),
"http_499": uint64(0),
"http_500": uint64(0),
"http_502": uint64(0),
"http_503": uint64(0),
"http_504": uint64(0),
"http_508": uint64(0),
"http_other_detail_status": uint64(0),
"http_ups_4xx": uint64(0),
"http_ups_5xx": uint64(0),
}
addr, err := url.Parse(ts.URL)
if err != nil {
panic(err)
}
host, port, err := net.SplitHostPort(addr.Host)
if err != nil {
host = addr.Host
if addr.Scheme == "http" {
port = "80"
} else if addr.Scheme == "https" {
port = "443"
} else {
port = ""
}
}
tags := map[string]string{"server": host, "port": port, "server_name": "127.0.0.1"}
accTengine.AssertContainsTaggedFields(t, "tengine", fieldsTengine, tags)
}