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,79 @@
# Nginx Input Plugin
This plugin gathers metrics from the open source [Nginx web server][nginx].
Nginx Plus is a commercial version. For more information about differences
between Nginx (F/OSS) and Nginx Plus, see the Nginx [documentation][diff_doc].
⭐ Telegraf v0.1.5
🏷️ server, web
💻 all
[nginx]: https://www.nginx.com
[diff_doc]: https://www.nginx.com/blog/whats-difference-nginx-foss-nginx-plus/
## 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 Nginx's basic status information (ngx_http_stub_status_module)
[[inputs.nginx]]
## An array of Nginx stub_status URI to gather stats.
urls = ["http://localhost/server_status"]
## 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
## HTTP response timeout (default: 5s)
response_timeout = "5s"
```
## Metrics
- Measurement
- accepts
- active
- handled
- reading
- requests
- waiting
- writing
## Tags
- All measurements have the following tags:
- port
- server
## Example Output
Using this configuration:
```toml
[[inputs.nginx]]
## An array of Nginx stub_status URI to gather stats.
urls = ["http://localhost/status"]
```
When run with:
```sh
./telegraf --config telegraf.conf --input-filter nginx --test
```
It produces:
```text
nginx,port=80,server=localhost accepts=605i,active=2i,handled=605i,reading=0i,requests=12132i,waiting=1i,writing=1i 1456690994701784331
```

View file

@ -0,0 +1,193 @@
//go:generate ../../../tools/readme_config_includer/generator
package nginx
import (
"bufio"
_ "embed"
"fmt"
"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 Nginx struct {
Urls []string `toml:"urls"`
ResponseTimeout config.Duration `toml:"response_timeout"`
tls.ClientConfig
// HTTP client
client *http.Client
}
func (*Nginx) SampleConfig() string {
return sampleConfig
}
func (n *Nginx) 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 *Nginx) 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 *Nginx) gatherURL(addr *url.URL, acc telegraf.Accumulator) error {
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)
// Active connections
_, err = r.ReadString(':')
if err != nil {
return err
}
line, err := r.ReadString('\n')
if err != nil {
return err
}
active, err := strconv.ParseUint(strings.TrimSpace(line), 10, 64)
if err != nil {
return err
}
// Server accepts handled requests
_, err = r.ReadString('\n')
if err != nil {
return err
}
line, err = r.ReadString('\n')
if err != nil {
return err
}
data := strings.Fields(line)
accepts, err := strconv.ParseUint(data[0], 10, 64)
if err != nil {
return err
}
handled, err := strconv.ParseUint(data[1], 10, 64)
if err != nil {
return err
}
requests, err := strconv.ParseUint(data[2], 10, 64)
if err != nil {
return err
}
// Reading/Writing/Waiting
line, err = r.ReadString('\n')
if err != nil {
return err
}
data = strings.Fields(line)
reading, err := strconv.ParseUint(data[1], 10, 64)
if err != nil {
return err
}
writing, err := strconv.ParseUint(data[3], 10, 64)
if err != nil {
return err
}
waiting, err := strconv.ParseUint(data[5], 10, 64)
if err != nil {
return err
}
tags := getTags(addr)
fields := map[string]interface{}{
"active": active,
"accepts": accepts,
"handled": handled,
"requests": requests,
"reading": reading,
"writing": writing,
"waiting": waiting,
}
acc.AddFields("nginx", fields, tags)
return nil
}
// Get tag(s) for the nginx plugin
func getTags(addr *url.URL) 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}
}
func init() {
inputs.Add("nginx", func() telegraf.Input {
return &Nginx{}
})
}

View file

@ -0,0 +1,114 @@
package nginx
import (
"fmt"
"net"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf/testutil"
)
const nginxSampleResponse = `
Active connections: 585
server accepts handled requests
85340 85340 35085
Reading: 4 Writing: 135 Waiting: 446
`
const tengineSampleResponse = `
Active connections: 403
server accepts handled requests request_time
853 8533 3502 1546565864
Reading: 8 Writing: 125 Waiting: 946
`
// Verify that nginx tags are properly parsed based on the server
func TestNginxTags(t *testing.T) {
urls := []string{"http://localhost/endpoint", "http://localhost:80/endpoint"}
for _, url1 := range urls {
addr, err := url.Parse(url1)
require.NoError(t, err)
tagMap := getTags(addr)
require.Contains(t, tagMap["server"], "localhost")
}
}
func TestNginxGeneratesMetrics(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var rsp string
if r.URL.Path == "/stub_status" {
rsp = nginxSampleResponse
} else if r.URL.Path == "/tengine_status" {
rsp = tengineSampleResponse
} else {
w.WriteHeader(http.StatusInternalServerError)
t.Errorf("Cannot handle request, unknown path")
return
}
if _, err := fmt.Fprintln(w, rsp); err != nil {
w.WriteHeader(http.StatusInternalServerError)
t.Error(err)
return
}
}))
defer ts.Close()
n := &Nginx{
Urls: []string{ts.URL + "/stub_status"},
}
nt := &Nginx{
Urls: []string{ts.URL + "/tengine_status"},
}
var accNginx testutil.Accumulator
var accTengine testutil.Accumulator
require.NoError(t, accNginx.GatherError(n.Gather))
require.NoError(t, accTengine.GatherError(nt.Gather))
fieldsNginx := map[string]interface{}{
"active": uint64(585),
"accepts": uint64(85340),
"handled": uint64(85340),
"requests": uint64(35085),
"reading": uint64(4),
"writing": uint64(135),
"waiting": uint64(446),
}
fieldsTengine := map[string]interface{}{
"active": uint64(403),
"accepts": uint64(853),
"handled": uint64(8533),
"requests": uint64(3502),
"reading": uint64(8),
"writing": uint64(125),
"waiting": uint64(946),
}
addr, err := url.Parse(ts.URL)
require.NoError(t, 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}
accNginx.AssertContainsTaggedFields(t, "nginx", fieldsNginx, tags)
accTengine.AssertContainsTaggedFields(t, "nginx", fieldsTengine, tags)
}

View file

@ -0,0 +1,14 @@
# Read Nginx's basic status information (ngx_http_stub_status_module)
[[inputs.nginx]]
## An array of Nginx stub_status URI to gather stats.
urls = ["http://localhost/server_status"]
## 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
## HTTP response timeout (default: 5s)
response_timeout = "5s"