chore: Fix linter findings for `revive:exported` in `plugins/inputs/n*` (#16205)
This commit is contained in:
parent
f80910be16
commit
3dea61cb5c
|
|
@ -23,8 +23,8 @@ import (
|
|||
var sampleConfig string
|
||||
|
||||
type Nats struct {
|
||||
Server string
|
||||
ResponseTimeout config.Duration
|
||||
Server string `toml:"server"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,27 +19,12 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
var once sync.Once
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
defaultMaxUndeliveredMessages = 1000
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
type semaphore chan empty
|
||||
|
||||
type natsError struct {
|
||||
conn *nats.Conn
|
||||
sub *nats.Subscription
|
||||
err error
|
||||
}
|
||||
|
||||
func (e natsError) Error() string {
|
||||
return fmt.Sprintf("%s url:%s id:%s sub:%s queue:%s",
|
||||
e.err.Error(), e.conn.ConnectedUrl(), e.conn.ConnectedServerId(), e.sub.Subject, e.sub.Queue)
|
||||
}
|
||||
|
||||
type natsConsumer struct {
|
||||
type NatsConsumer struct {
|
||||
QueueGroup string `toml:"queue_group"`
|
||||
Subjects []string `toml:"subjects"`
|
||||
Servers []string `toml:"servers"`
|
||||
|
|
@ -70,24 +55,32 @@ type natsConsumer struct {
|
|||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (*natsConsumer) SampleConfig() string {
|
||||
type (
|
||||
empty struct{}
|
||||
semaphore chan empty
|
||||
)
|
||||
|
||||
type natsError struct {
|
||||
conn *nats.Conn
|
||||
sub *nats.Subscription
|
||||
err error
|
||||
}
|
||||
|
||||
func (e natsError) Error() string {
|
||||
return fmt.Sprintf("%s url:%s id:%s sub:%s queue:%s",
|
||||
e.err.Error(), e.conn.ConnectedUrl(), e.conn.ConnectedServerId(), e.sub.Subject, e.sub.Queue)
|
||||
}
|
||||
|
||||
func (*NatsConsumer) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (n *natsConsumer) SetParser(parser telegraf.Parser) {
|
||||
func (n *NatsConsumer) SetParser(parser telegraf.Parser) {
|
||||
n.parser = parser
|
||||
}
|
||||
|
||||
func (n *natsConsumer) natsErrHandler(c *nats.Conn, s *nats.Subscription, e error) {
|
||||
select {
|
||||
case n.errs <- natsError{conn: c, sub: s, err: e}:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Start the nats consumer. Caller must call *natsConsumer.Stop() to clean up.
|
||||
func (n *natsConsumer) Start(acc telegraf.Accumulator) error {
|
||||
// Start the nats consumer. Caller must call *NatsConsumer.Stop() to clean up.
|
||||
func (n *NatsConsumer) Start(acc telegraf.Accumulator) error {
|
||||
n.acc = acc.WithTracking(n.MaxUndeliveredMessages)
|
||||
|
||||
options := []nats.Option{
|
||||
|
|
@ -193,9 +186,27 @@ func (n *natsConsumer) Start(acc telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NatsConsumer) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NatsConsumer) Stop() {
|
||||
n.cancel()
|
||||
n.wg.Wait()
|
||||
n.clean()
|
||||
}
|
||||
|
||||
func (n *NatsConsumer) natsErrHandler(c *nats.Conn, s *nats.Subscription, e error) {
|
||||
select {
|
||||
case n.errs <- natsError{conn: c, sub: s, err: e}:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// receiver() reads all incoming messages from NATS, and parses them into
|
||||
// telegraf metrics.
|
||||
func (n *natsConsumer) receiver(ctx context.Context) {
|
||||
func (n *NatsConsumer) receiver(ctx context.Context) {
|
||||
sem := make(semaphore, n.MaxUndeliveredMessages)
|
||||
|
||||
for {
|
||||
|
|
@ -237,7 +248,7 @@ func (n *natsConsumer) receiver(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *natsConsumer) clean() {
|
||||
func (n *NatsConsumer) clean() {
|
||||
for _, sub := range n.subs {
|
||||
if err := sub.Unsubscribe(); err != nil {
|
||||
n.Log.Errorf("Error unsubscribing from subject %s in queue %s: %s",
|
||||
|
|
@ -257,19 +268,9 @@ func (n *natsConsumer) clean() {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *natsConsumer) Stop() {
|
||||
n.cancel()
|
||||
n.wg.Wait()
|
||||
n.clean()
|
||||
}
|
||||
|
||||
func (n *natsConsumer) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nats_consumer", func() telegraf.Input {
|
||||
return &natsConsumer{
|
||||
return &NatsConsumer{
|
||||
Servers: []string{"nats://localhost:4222"},
|
||||
Subjects: []string{"telegraf"},
|
||||
QueueGroup: "telegraf_consumers",
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func TestStartStop(t *testing.T) {
|
|||
require.NoError(t, container.Start(), "failed to start container")
|
||||
defer container.Terminate()
|
||||
|
||||
plugin := &natsConsumer{
|
||||
plugin := &NatsConsumer{
|
||||
Servers: []string{fmt.Sprintf("nats://%s:%s", container.Address, container.Ports["4222"])},
|
||||
Subjects: []string{"telegraf"},
|
||||
QueueGroup: "telegraf_consumers",
|
||||
|
|
@ -140,7 +140,7 @@ func TestSendReceive(t *testing.T) {
|
|||
}
|
||||
|
||||
// Setup the plugin
|
||||
plugin := &natsConsumer{
|
||||
plugin := &NatsConsumer{
|
||||
Servers: []string{addr},
|
||||
Subjects: subjects,
|
||||
QueueGroup: "telegraf_consumers",
|
||||
|
|
@ -161,15 +161,15 @@ func TestSendReceive(t *testing.T) {
|
|||
defer plugin.Stop()
|
||||
|
||||
// Send all messages to the topics (random order due to Golang map)
|
||||
publisher := &sender{Addr: addr}
|
||||
require.NoError(t, publisher.Connect())
|
||||
defer publisher.Disconnect()
|
||||
publisher := &sender{addr: addr}
|
||||
require.NoError(t, publisher.connect())
|
||||
defer publisher.disconnect()
|
||||
for topic, msgs := range tt.msgs {
|
||||
for _, msg := range msgs {
|
||||
require.NoError(t, publisher.Send(topic, msg))
|
||||
require.NoError(t, publisher.send(topic, msg))
|
||||
}
|
||||
}
|
||||
publisher.Disconnect()
|
||||
publisher.disconnect()
|
||||
|
||||
// Wait for the metrics to be collected
|
||||
require.Eventually(t, func() bool {
|
||||
|
|
@ -185,16 +185,12 @@ func TestSendReceive(t *testing.T) {
|
|||
}
|
||||
|
||||
type sender struct {
|
||||
Addr string
|
||||
|
||||
Username string
|
||||
Password string
|
||||
|
||||
addr string
|
||||
conn *nats.Conn
|
||||
}
|
||||
|
||||
func (s *sender) Connect() error {
|
||||
conn, err := nats.Connect(s.Addr)
|
||||
func (s *sender) connect() error {
|
||||
conn, err := nats.Connect(s.addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -203,7 +199,7 @@ func (s *sender) Connect() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *sender) Disconnect() {
|
||||
func (s *sender) disconnect() {
|
||||
if s.conn != nil && !s.conn.IsClosed() {
|
||||
_ = s.conn.Flush()
|
||||
s.conn.Close()
|
||||
|
|
@ -211,6 +207,6 @@ func (s *sender) Disconnect() {
|
|||
s.conn = nil
|
||||
}
|
||||
|
||||
func (s *sender) Send(topic, msg string) error {
|
||||
func (s *sender) send(topic, msg string) error {
|
||||
return s.conn.Publish(topic, []byte(msg))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,12 +68,6 @@ func (n *NeoomBeaam) Start(telegraf.Accumulator) error {
|
|||
return n.updateConfiguration()
|
||||
}
|
||||
|
||||
func (n *NeoomBeaam) Stop() {
|
||||
if n.client != nil {
|
||||
n.client.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NeoomBeaam) Gather(acc telegraf.Accumulator) error {
|
||||
// Refresh the config if requested
|
||||
if n.RefreshConfig {
|
||||
|
|
@ -97,6 +91,12 @@ func (n *NeoomBeaam) Gather(acc telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NeoomBeaam) Stop() {
|
||||
if n.client != nil {
|
||||
n.client.CloseIdleConnections()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *NeoomBeaam) updateConfiguration() error {
|
||||
endpoint := n.Address + "/api/v1/site/configuration"
|
||||
request, err := http.NewRequest("GET", endpoint, nil)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,12 @@ var sampleConfig string
|
|||
// Measurement is constant across all metrics.
|
||||
const Measurement = "neptune_apex"
|
||||
|
||||
type NeptuneApex struct {
|
||||
Servers []string `toml:"servers"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
type xmlReply struct {
|
||||
SoftwareVersion string `xml:"software,attr"`
|
||||
HardwareVersion string `xml:"hardware,attr"`
|
||||
|
|
@ -54,18 +60,10 @@ type outlet struct {
|
|||
Xstatus *string `xml:"xstatus"`
|
||||
}
|
||||
|
||||
// NeptuneApex implements telegraf.Input.
|
||||
type NeptuneApex struct {
|
||||
Servers []string
|
||||
ResponseTimeout config.Duration
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func (*NeptuneApex) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Gather implements telegraf.Input.Gather
|
||||
func (n *NeptuneApex) Gather(acc telegraf.Accumulator) error {
|
||||
var wg sync.WaitGroup
|
||||
for _, server := range n.Servers {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func TestParseXML(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "Good test",
|
||||
xmlResponse: []byte(APEX2016),
|
||||
xmlResponse: []byte(apex2016),
|
||||
wantMetrics: []telegraf.Metric{
|
||||
testutil.MustMetric(
|
||||
Measurement,
|
||||
|
|
@ -532,7 +532,7 @@ func fakeHTTPClient(h http.Handler) (*http.Client, func()) {
|
|||
}
|
||||
|
||||
// Sample configuration from a 2016 version Neptune Apex.
|
||||
const APEX2016 = `<?xml version="1.0"?>
|
||||
const apex2016 = `<?xml version="1.0"?>
|
||||
<status software="5.04_7A18" hardware="1.0">
|
||||
<hostname>apex</hostname>
|
||||
<serial>AC5:12345</serial>
|
||||
|
|
|
|||
|
|
@ -21,20 +21,20 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type NetIOStats struct {
|
||||
filter filter.Filter
|
||||
ps system.PS
|
||||
type Net struct {
|
||||
Interfaces []string `toml:"interfaces"`
|
||||
IgnoreProtocolStats bool `toml:"ignore_protocol_stats"`
|
||||
|
||||
skipChecks bool
|
||||
IgnoreProtocolStats bool
|
||||
Interfaces []string
|
||||
filter filter.Filter
|
||||
ps system.PS
|
||||
skipChecks bool
|
||||
}
|
||||
|
||||
func (*NetIOStats) SampleConfig() string {
|
||||
func (*Net) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (n *NetIOStats) Init() error {
|
||||
func (n *Net) Init() error {
|
||||
if !n.IgnoreProtocolStats {
|
||||
config.PrintOptionValueDeprecationNotice("inputs.net", "ignore_protocol_stats", "false",
|
||||
telegraf.DeprecationInfo{
|
||||
|
|
@ -48,7 +48,7 @@ func (n *NetIOStats) Init() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NetIOStats) Gather(acc telegraf.Accumulator) error {
|
||||
func (n *Net) Gather(acc telegraf.Accumulator) error {
|
||||
netio, err := n.ps.NetIO()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting net io info: %w", err)
|
||||
|
|
@ -153,6 +153,6 @@ func getInterfaceSpeed(ioName string) int64 {
|
|||
|
||||
func init() {
|
||||
inputs.Add("net", func() telegraf.Input {
|
||||
return &NetIOStats{ps: system.NewSystemPS()}
|
||||
return &Net{ps: system.NewSystemPS()}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ func TestNetIOStats(t *testing.T) {
|
|||
|
||||
t.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys"))
|
||||
|
||||
plugin := &NetIOStats{ps: &mps, skipChecks: true}
|
||||
plugin := &Net{ps: &mps, skipChecks: true}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
|
|
@ -111,7 +111,7 @@ func TestNetIOStatsSpeedUnsupported(t *testing.T) {
|
|||
|
||||
t.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys"))
|
||||
|
||||
plugin := &NetIOStats{ps: &mps, skipChecks: true}
|
||||
plugin := &Net{ps: &mps, skipChecks: true}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
|
|
@ -178,7 +178,7 @@ func TestNetIOStatsNoSpeedFile(t *testing.T) {
|
|||
|
||||
t.Setenv("HOST_SYS", filepath.Join("testdata", "general", "sys"))
|
||||
|
||||
plugin := &NetIOStats{ps: &mps, skipChecks: true}
|
||||
plugin := &Net{ps: &mps, skipChecks: true}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, plugin.Gather(&acc))
|
||||
|
|
|
|||
|
|
@ -20,155 +20,29 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type ResultType uint64
|
||||
type resultType uint64
|
||||
|
||||
const (
|
||||
Success ResultType = 0
|
||||
Timeout ResultType = 1
|
||||
ConnectionFailed ResultType = 2
|
||||
ReadFailed ResultType = 3
|
||||
StringMismatch ResultType = 4
|
||||
success resultType = 0
|
||||
timeout resultType = 1
|
||||
connectionFailed resultType = 2
|
||||
readFailed resultType = 3
|
||||
stringMismatch resultType = 4
|
||||
)
|
||||
|
||||
// NetResponse struct
|
||||
type NetResponse struct {
|
||||
Address string
|
||||
Timeout config.Duration
|
||||
ReadTimeout config.Duration
|
||||
Send string
|
||||
Expect string
|
||||
Protocol string
|
||||
Address string `toml:"address"`
|
||||
Timeout config.Duration `toml:"timeout"`
|
||||
ReadTimeout config.Duration `toml:"read_timeout"`
|
||||
Send string `toml:"send"`
|
||||
Expect string `toml:"expect"`
|
||||
Protocol string `toml:"protocol"`
|
||||
}
|
||||
|
||||
func (*NetResponse) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// TCPGather will execute if there are TCP tests defined in the configuration.
|
||||
// It will return a map[string]interface{} for fields and a map[string]string for tags
|
||||
func (n *NetResponse) TCPGather() (map[string]string, map[string]interface{}, error) {
|
||||
// Prepare returns
|
||||
tags := make(map[string]string)
|
||||
fields := make(map[string]interface{})
|
||||
// Start Timer
|
||||
start := time.Now()
|
||||
// Connecting
|
||||
conn, err := net.DialTimeout("tcp", n.Address, time.Duration(n.Timeout))
|
||||
// Stop timer
|
||||
responseTime := time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
var e net.Error
|
||||
if errors.As(err, &e) && e.Timeout() {
|
||||
setResult(Timeout, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(ConnectionFailed, fields, tags, n.Expect)
|
||||
}
|
||||
return tags, fields, nil
|
||||
}
|
||||
defer conn.Close()
|
||||
// Send string if needed
|
||||
if n.Send != "" {
|
||||
msg := []byte(n.Send)
|
||||
if _, gerr := conn.Write(msg); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Stop timer
|
||||
responseTime = time.Since(start).Seconds()
|
||||
}
|
||||
// Read string if needed
|
||||
if n.Expect != "" {
|
||||
// Set read timeout
|
||||
if gerr := conn.SetReadDeadline(time.Now().Add(time.Duration(n.ReadTimeout))); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Prepare reader
|
||||
reader := bufio.NewReader(conn)
|
||||
tp := textproto.NewReader(reader)
|
||||
// Read
|
||||
data, err := tp.ReadLine()
|
||||
// Stop timer
|
||||
responseTime = time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(ReadFailed, fields, tags, n.Expect)
|
||||
} else {
|
||||
// Looking for string in answer
|
||||
regEx := regexp.MustCompile(`.*` + n.Expect + `.*`)
|
||||
find := regEx.FindString(data)
|
||||
if find != "" {
|
||||
setResult(Success, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(StringMismatch, fields, tags, n.Expect)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setResult(Success, fields, tags, n.Expect)
|
||||
}
|
||||
fields["response_time"] = responseTime
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
// UDPGather will execute if there are UDP tests defined in the configuration.
|
||||
// It will return a map[string]interface{} for fields and a map[string]string for tags
|
||||
func (n *NetResponse) UDPGather() (map[string]string, map[string]interface{}, error) {
|
||||
// Prepare returns
|
||||
tags := make(map[string]string)
|
||||
fields := make(map[string]interface{})
|
||||
// Start Timer
|
||||
start := time.Now()
|
||||
// Resolving
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", n.Address)
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(ConnectionFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
// Connecting
|
||||
conn, err := net.DialUDP("udp", nil, udpAddr)
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(ConnectionFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
defer conn.Close()
|
||||
// Send string
|
||||
msg := []byte(n.Send)
|
||||
if _, gerr := conn.Write(msg); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Read string
|
||||
// Set read timeout
|
||||
if gerr := conn.SetReadDeadline(time.Now().Add(time.Duration(n.ReadTimeout))); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Read
|
||||
buf := make([]byte, 1024)
|
||||
_, _, err = conn.ReadFromUDP(buf)
|
||||
// Stop timer
|
||||
responseTime := time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(ReadFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
// Looking for string in answer
|
||||
regEx := regexp.MustCompile(`.*` + n.Expect + `.*`)
|
||||
find := regEx.FindString(string(buf))
|
||||
if find != "" {
|
||||
setResult(Success, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(StringMismatch, fields, tags, n.Expect)
|
||||
}
|
||||
|
||||
fields["response_time"] = responseTime
|
||||
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
// Init performs one time setup of the plugin and returns an error if the
|
||||
// configuration is invalid.
|
||||
func (n *NetResponse) Init() error {
|
||||
// Set default values
|
||||
if n.Timeout == 0 {
|
||||
|
|
@ -203,9 +77,6 @@ func (n *NetResponse) Init() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Gather is called by telegraf when the plugin is executed on its interval.
|
||||
// It will call either UDPGather or TCPGather based on the configuration and
|
||||
// also fill an Accumulator that is supplied.
|
||||
func (n *NetResponse) Gather(acc telegraf.Accumulator) error {
|
||||
// Prepare host and port
|
||||
host, port, err := net.SplitHostPort(n.Address)
|
||||
|
|
@ -221,13 +92,13 @@ func (n *NetResponse) Gather(acc telegraf.Accumulator) error {
|
|||
// Gather data
|
||||
switch n.Protocol {
|
||||
case "tcp":
|
||||
returnTags, fields, err = n.TCPGather()
|
||||
returnTags, fields, err = n.tcpGather()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tags["protocol"] = "tcp"
|
||||
case "udp":
|
||||
returnTags, fields, err = n.UDPGather()
|
||||
returnTags, fields, err = n.udpGather()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -243,18 +114,137 @@ func (n *NetResponse) Gather(acc telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func setResult(result ResultType, fields map[string]interface{}, tags map[string]string, expect string) {
|
||||
func (n *NetResponse) tcpGather() (map[string]string, map[string]interface{}, error) {
|
||||
// Prepare returns
|
||||
tags := make(map[string]string)
|
||||
fields := make(map[string]interface{})
|
||||
// Start Timer
|
||||
start := time.Now()
|
||||
// Connecting
|
||||
conn, err := net.DialTimeout("tcp", n.Address, time.Duration(n.Timeout))
|
||||
// Stop timer
|
||||
responseTime := time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
var e net.Error
|
||||
if errors.As(err, &e) && e.Timeout() {
|
||||
setResult(timeout, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(connectionFailed, fields, tags, n.Expect)
|
||||
}
|
||||
return tags, fields, nil
|
||||
}
|
||||
defer conn.Close()
|
||||
// Send string if needed
|
||||
if n.Send != "" {
|
||||
msg := []byte(n.Send)
|
||||
if _, gerr := conn.Write(msg); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Stop timer
|
||||
responseTime = time.Since(start).Seconds()
|
||||
}
|
||||
// Read string if needed
|
||||
if n.Expect != "" {
|
||||
// Set read timeout
|
||||
if gerr := conn.SetReadDeadline(time.Now().Add(time.Duration(n.ReadTimeout))); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Prepare reader
|
||||
reader := bufio.NewReader(conn)
|
||||
tp := textproto.NewReader(reader)
|
||||
// Read
|
||||
data, err := tp.ReadLine()
|
||||
// Stop timer
|
||||
responseTime = time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(readFailed, fields, tags, n.Expect)
|
||||
} else {
|
||||
// Looking for string in answer
|
||||
regEx := regexp.MustCompile(`.*` + n.Expect + `.*`)
|
||||
find := regEx.FindString(data)
|
||||
if find != "" {
|
||||
setResult(success, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(stringMismatch, fields, tags, n.Expect)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setResult(success, fields, tags, n.Expect)
|
||||
}
|
||||
fields["response_time"] = responseTime
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
func (n *NetResponse) udpGather() (map[string]string, map[string]interface{}, error) {
|
||||
// Prepare returns
|
||||
tags := make(map[string]string)
|
||||
fields := make(map[string]interface{})
|
||||
// Start Timer
|
||||
start := time.Now()
|
||||
// Resolving
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", n.Address)
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(connectionFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
// Connecting
|
||||
conn, err := net.DialUDP("udp", nil, udpAddr)
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(connectionFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
defer conn.Close()
|
||||
// Send string
|
||||
msg := []byte(n.Send)
|
||||
if _, gerr := conn.Write(msg); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Read string
|
||||
// Set read timeout
|
||||
if gerr := conn.SetReadDeadline(time.Now().Add(time.Duration(n.ReadTimeout))); gerr != nil {
|
||||
return nil, nil, gerr
|
||||
}
|
||||
// Read
|
||||
buf := make([]byte, 1024)
|
||||
_, _, err = conn.ReadFromUDP(buf)
|
||||
// Stop timer
|
||||
responseTime := time.Since(start).Seconds()
|
||||
// Handle error
|
||||
if err != nil {
|
||||
setResult(readFailed, fields, tags, n.Expect)
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
// Looking for string in answer
|
||||
regEx := regexp.MustCompile(`.*` + n.Expect + `.*`)
|
||||
find := regEx.FindString(string(buf))
|
||||
if find != "" {
|
||||
setResult(success, fields, tags, n.Expect)
|
||||
} else {
|
||||
setResult(stringMismatch, fields, tags, n.Expect)
|
||||
}
|
||||
|
||||
fields["response_time"] = responseTime
|
||||
|
||||
return tags, fields, nil
|
||||
}
|
||||
|
||||
func setResult(result resultType, fields map[string]interface{}, tags map[string]string, expect string) {
|
||||
var tag string
|
||||
switch result {
|
||||
case Success:
|
||||
case success:
|
||||
tag = "success"
|
||||
case Timeout:
|
||||
case timeout:
|
||||
tag = "timeout"
|
||||
case ConnectionFailed:
|
||||
case connectionFailed:
|
||||
tag = "connection_failed"
|
||||
case ReadFailed:
|
||||
case readFailed:
|
||||
tag = "read_failed"
|
||||
case StringMismatch:
|
||||
case stringMismatch:
|
||||
tag = "string_mismatch"
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +256,7 @@ func setResult(result ResultType, fields map[string]interface{}, tags map[string
|
|||
|
||||
// deprecated in 1.4; use result tag
|
||||
if expect != "" {
|
||||
fields["string_found"] = result == Success
|
||||
fields["string_found"] = result == success
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func TestTCPOK1(t *testing.T) {
|
|||
require.NoError(t, c.Init())
|
||||
// Start TCP server
|
||||
wg.Add(1)
|
||||
go TCPServer(t, &wg)
|
||||
go tcpServer(t, &wg)
|
||||
wg.Wait() // Wait for the server to spin up
|
||||
wg.Add(1)
|
||||
// Connect
|
||||
|
|
@ -151,7 +151,7 @@ func TestTCPOK2(t *testing.T) {
|
|||
require.NoError(t, c.Init())
|
||||
// Start TCP server
|
||||
wg.Add(1)
|
||||
go TCPServer(t, &wg)
|
||||
go tcpServer(t, &wg)
|
||||
wg.Wait()
|
||||
wg.Add(1)
|
||||
|
||||
|
|
@ -233,7 +233,7 @@ func TestUDPOK1(t *testing.T) {
|
|||
require.NoError(t, c.Init())
|
||||
// Start UDP server
|
||||
wg.Add(1)
|
||||
go UDPServer(t, &wg)
|
||||
go udpServer(t, &wg)
|
||||
wg.Wait()
|
||||
wg.Add(1)
|
||||
|
||||
|
|
@ -264,7 +264,7 @@ func TestUDPOK1(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
func UDPServer(t *testing.T, wg *sync.WaitGroup) {
|
||||
func udpServer(t *testing.T, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
udpAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:2004")
|
||||
if err != nil {
|
||||
|
|
@ -297,7 +297,7 @@ func UDPServer(t *testing.T, wg *sync.WaitGroup) {
|
|||
}
|
||||
}
|
||||
|
||||
func TCPServer(t *testing.T, wg *sync.WaitGroup) {
|
||||
func tcpServer(t *testing.T, wg *sync.WaitGroup) {
|
||||
defer wg.Done()
|
||||
tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:2004")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -19,11 +19,6 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type protocolDecoder interface {
|
||||
Init() error
|
||||
Decode(net.IP, []byte) ([]telegraf.Metric, error)
|
||||
}
|
||||
|
||||
type NetFlow struct {
|
||||
ServiceAddress string `toml:"service_address"`
|
||||
ReadBufferSize config.Size `toml:"read_buffer_size"`
|
||||
|
|
@ -37,6 +32,11 @@ type NetFlow struct {
|
|||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
type protocolDecoder interface {
|
||||
init() error
|
||||
decode(net.IP, []byte) ([]telegraf.Metric, error)
|
||||
}
|
||||
|
||||
func (*NetFlow) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
|
@ -61,12 +61,12 @@ func (n *NetFlow) Init() error {
|
|||
n.Log.Warn("'private_enterprise_number_files' option will be ignored in 'netflow v9'")
|
||||
}
|
||||
n.decoder = &netflowDecoder{
|
||||
Log: n.Log,
|
||||
log: n.Log,
|
||||
}
|
||||
case "", "ipfix":
|
||||
n.decoder = &netflowDecoder{
|
||||
PENFiles: n.PENFiles,
|
||||
Log: n.Log,
|
||||
penFiles: n.PENFiles,
|
||||
log: n.Log,
|
||||
}
|
||||
case "netflow v5":
|
||||
if len(n.PENFiles) != 0 {
|
||||
|
|
@ -74,12 +74,12 @@ func (n *NetFlow) Init() error {
|
|||
}
|
||||
n.decoder = &netflowv5Decoder{}
|
||||
case "sflow", "sflow v5":
|
||||
n.decoder = &sflowv5Decoder{Log: n.Log}
|
||||
n.decoder = &sflowv5Decoder{log: n.Log}
|
||||
default:
|
||||
return fmt.Errorf("invalid protocol %q, only supports 'sflow', 'netflow v5', 'netflow v9' and 'ipfix'", n.Protocol)
|
||||
}
|
||||
|
||||
return n.decoder.Init()
|
||||
return n.decoder.init()
|
||||
}
|
||||
|
||||
func (n *NetFlow) Start(acc telegraf.Accumulator) error {
|
||||
|
|
@ -114,6 +114,10 @@ func (n *NetFlow) Start(acc telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NetFlow) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NetFlow) Stop() {
|
||||
if n.conn != nil {
|
||||
_ = n.conn.Close()
|
||||
|
|
@ -138,7 +142,7 @@ func (n *NetFlow) read(acc telegraf.Accumulator) {
|
|||
if n.Log.Level().Includes(telegraf.Trace) || n.DumpPackets { // for backward compatibility
|
||||
n.Log.Tracef("raw data: %s", hex.EncodeToString(buf[:count]))
|
||||
}
|
||||
metrics, err := n.decoder.Decode(src.IP, buf[:count])
|
||||
metrics, err := n.decoder.decode(src.IP, buf[:count])
|
||||
if err != nil {
|
||||
errWithData := fmt.Errorf("%w; raw data: %s", err, hex.EncodeToString(buf[:count]))
|
||||
acc.AddError(errWithData)
|
||||
|
|
@ -150,10 +154,6 @@ func (n *NetFlow) read(acc telegraf.Accumulator) {
|
|||
}
|
||||
}
|
||||
|
||||
func (n *NetFlow) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Register the plugin
|
||||
func init() {
|
||||
inputs.Add("netflow", func() telegraf.Input {
|
||||
|
|
|
|||
|
|
@ -530,8 +530,8 @@ var fieldMappingsIPFIX = map[uint16][]fieldMapping{
|
|||
|
||||
// Decoder structure
|
||||
type netflowDecoder struct {
|
||||
PENFiles []string
|
||||
Log telegraf.Logger
|
||||
penFiles []string
|
||||
log telegraf.Logger
|
||||
|
||||
templates map[string]netflow.NetFlowTemplateSystem
|
||||
mappingsV9 map[uint16]fieldMapping
|
||||
|
|
@ -542,7 +542,7 @@ type netflowDecoder struct {
|
|||
sync.Mutex
|
||||
}
|
||||
|
||||
func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
func (d *netflowDecoder) decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
var metrics []telegraf.Metric
|
||||
|
||||
t := time.Now()
|
||||
|
|
@ -563,7 +563,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
if err := netflow.DecodeMessageVersion(buf, templates, &msg9, &msg10); err != nil {
|
||||
if errors.Is(err, netflow.ErrorTemplateNotFound) {
|
||||
msg := "Skipping packet until the device resends the required template..."
|
||||
d.Log.Warnf("%v. %s", err, msg)
|
||||
d.log.Warnf("%v. %s", err, msg)
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("decoding message failed: %w", err)
|
||||
|
|
@ -587,7 +587,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.ScopesValues {
|
||||
decodedFields, err := d.decodeValueV9(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
d.log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -597,7 +597,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.OptionsValues {
|
||||
decodedFields, err := d.decodeValueV9(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
d.log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -616,7 +616,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.Values {
|
||||
decodedFields, err := d.decodeValueV9(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding record %+v failed: %v", record, err)
|
||||
d.log.Errorf("decoding record %+v failed: %v", record, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -643,7 +643,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.ScopesValues {
|
||||
decodedFields, err := d.decodeValueIPFIX(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
d.log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -653,7 +653,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.OptionsValues {
|
||||
decodedFields, err := d.decodeValueIPFIX(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
d.log.Errorf("decoding option record %+v failed: %v", record, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -673,7 +673,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
for _, value := range record.Values {
|
||||
decodedFields, err := d.decodeValueIPFIX(value)
|
||||
if err != nil {
|
||||
d.Log.Errorf("decoding value %+v failed: %v", value, err)
|
||||
d.log.Errorf("decoding value %+v failed: %v", value, err)
|
||||
continue
|
||||
}
|
||||
for _, field := range decodedFields {
|
||||
|
|
@ -691,7 +691,7 @@ func (d *netflowDecoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric
|
|||
return metrics, nil
|
||||
}
|
||||
|
||||
func (d *netflowDecoder) Init() error {
|
||||
func (d *netflowDecoder) init() error {
|
||||
if err := initL4ProtoMapping(); err != nil {
|
||||
return fmt.Errorf("initializing layer 4 protocol mapping failed: %w", err)
|
||||
}
|
||||
|
|
@ -703,8 +703,8 @@ func (d *netflowDecoder) Init() error {
|
|||
d.mappingsV9 = make(map[uint16]fieldMapping)
|
||||
d.mappingsIPFIX = make(map[uint16]fieldMapping)
|
||||
d.mappingsPEN = make(map[string]fieldMapping)
|
||||
for _, fn := range d.PENFiles {
|
||||
d.Log.Debugf("Loading PEN mapping file %q...", fn)
|
||||
for _, fn := range d.penFiles {
|
||||
d.log.Debugf("Loading PEN mapping file %q...", fn)
|
||||
mappings, err := loadMapping(fn)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -719,7 +719,7 @@ func (d *netflowDecoder) Init() error {
|
|||
d.mappingsPEN[k] = v
|
||||
}
|
||||
}
|
||||
d.Log.Infof("Loaded %d PEN mappings...", len(d.mappingsPEN))
|
||||
d.log.Infof("Loaded %d PEN mappings...", len(d.mappingsPEN))
|
||||
|
||||
d.logged = make(map[string]bool)
|
||||
|
||||
|
|
@ -783,7 +783,7 @@ func (d *netflowDecoder) decodeValueV9(field netflow.DataField) ([]telegraf.Fiel
|
|||
// Return the raw data if no mapping was found
|
||||
key := fmt.Sprintf("type_%d", elementID)
|
||||
if !d.logged[key] {
|
||||
d.Log.Debugf("unknown Netflow v9 data field %v", field)
|
||||
d.log.Debugf("unknown Netflow v9 data field %v", field)
|
||||
d.logged[key] = true
|
||||
}
|
||||
v, err := decodeHex(raw)
|
||||
|
|
@ -817,7 +817,7 @@ func (d *netflowDecoder) decodeValueIPFIX(field netflow.DataField) ([]telegraf.F
|
|||
return []telegraf.Field{{Key: name, Value: v}}, nil
|
||||
}
|
||||
if !d.logged[key] {
|
||||
d.Log.Debugf("unknown IPFIX PEN data field %v", field)
|
||||
d.log.Debugf("unknown IPFIX PEN data field %v", field)
|
||||
d.logged[key] = true
|
||||
}
|
||||
name := fmt.Sprintf("type_%d_%s%d", field.Pen, prefix, elementID)
|
||||
|
|
@ -866,7 +866,7 @@ func (d *netflowDecoder) decodeValueIPFIX(field netflow.DataField) ([]telegraf.F
|
|||
// Return the raw data if no mapping was found
|
||||
key := fmt.Sprintf("type_%d", elementID)
|
||||
if !d.logged[key] {
|
||||
d.Log.Debugf("unknown IPFIX data field %v", field)
|
||||
d.log.Debugf("unknown IPFIX data field %v", field)
|
||||
d.logged[key] = true
|
||||
}
|
||||
v, err := decodeHex(raw)
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ import (
|
|||
// Decoder structure
|
||||
type netflowv5Decoder struct{}
|
||||
|
||||
func (d *netflowv5Decoder) Init() error {
|
||||
func (d *netflowv5Decoder) init() error {
|
||||
if err := initL4ProtoMapping(); err != nil {
|
||||
return fmt.Errorf("initializing layer 4 protocol mapping failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *netflowv5Decoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
func (d *netflowv5Decoder) decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
src := srcIP.String()
|
||||
|
||||
// Decode the message
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ import (
|
|||
|
||||
// Decoder structure
|
||||
type sflowv5Decoder struct {
|
||||
Log telegraf.Logger
|
||||
log telegraf.Logger
|
||||
|
||||
warnedCounterRaw map[uint32]bool
|
||||
warnedFlowRaw map[int64]bool
|
||||
}
|
||||
|
||||
func (d *sflowv5Decoder) Init() error {
|
||||
func (d *sflowv5Decoder) init() error {
|
||||
if err := initL4ProtoMapping(); err != nil {
|
||||
return fmt.Errorf("initializing layer 4 protocol mapping failed: %w", err)
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ func (d *sflowv5Decoder) Init() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *sflowv5Decoder) Decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
func (d *sflowv5Decoder) decode(srcIP net.IP, payload []byte) ([]telegraf.Metric, error) {
|
||||
t := time.Now()
|
||||
src := srcIP.String()
|
||||
|
||||
|
|
@ -448,11 +448,11 @@ func (d *sflowv5Decoder) decodeRawHeaderSample(record *sflow.SampledHeader) (map
|
|||
if !d.warnedFlowRaw[ltype] {
|
||||
contents := hex.EncodeToString(pkt.LayerContents())
|
||||
payload := hex.EncodeToString(pkt.LayerPayload())
|
||||
d.Log.Warnf("Unknown flow raw flow message %s (%d):", pkt.LayerType().String(), pkt.LayerType())
|
||||
d.Log.Warnf(" contents: %s", contents)
|
||||
d.Log.Warnf(" payload: %s", payload)
|
||||
d.log.Warnf("Unknown flow raw flow message %s (%d):", pkt.LayerType().String(), pkt.LayerType())
|
||||
d.log.Warnf(" contents: %s", contents)
|
||||
d.log.Warnf(" payload: %s", payload)
|
||||
|
||||
d.Log.Warn("This message is only printed once.")
|
||||
d.log.Warn("This message is only printed once.")
|
||||
}
|
||||
d.warnedFlowRaw[ltype] = true
|
||||
}
|
||||
|
|
@ -524,8 +524,8 @@ func (d *sflowv5Decoder) decodeCounterRecords(records []sflow.CounterRecord) (ma
|
|||
default:
|
||||
if !d.warnedCounterRaw[r.Header.DataFormat] {
|
||||
data := hex.EncodeToString(record.Data)
|
||||
d.Log.Warnf("Unknown counter raw flow message %d: %s", r.Header.DataFormat, data)
|
||||
d.Log.Warn("This message is only printed once.")
|
||||
d.log.Warnf("Unknown counter raw flow message %d: %s", r.Header.DataFormat, data)
|
||||
d.log.Warn("This message is only printed once.")
|
||||
}
|
||||
d.warnedCounterRaw[r.Header.DataFormat] = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,16 +14,16 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type NetStats struct {
|
||||
PS system.PS
|
||||
type NetStat struct {
|
||||
ps system.PS
|
||||
}
|
||||
|
||||
func (*NetStats) SampleConfig() string {
|
||||
func (*NetStat) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (ns *NetStats) Gather(acc telegraf.Accumulator) error {
|
||||
netconns, err := ns.PS.NetConnections()
|
||||
func (ns *NetStat) Gather(acc telegraf.Accumulator) error {
|
||||
netconns, err := ns.ps.NetConnections()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting net connections info: %w", err)
|
||||
}
|
||||
|
|
@ -66,6 +66,6 @@ func (ns *NetStats) Gather(acc telegraf.Accumulator) error {
|
|||
|
||||
func init() {
|
||||
inputs.Add("netstat", func() telegraf.Input {
|
||||
return &NetStats{PS: system.NewSystemPS()}
|
||||
return &NetStat{ps: system.NewSystemPS()}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func TestNetStats(t *testing.T) {
|
|||
}, nil)
|
||||
|
||||
var acc testutil.Accumulator
|
||||
require.NoError(t, (&NetStats{PS: &mps}).Gather(&acc))
|
||||
require.NoError(t, (&NetStat{ps: &mps}).Gather(&acc))
|
||||
|
||||
expected := []telegraf.Metric{
|
||||
metric.New(
|
||||
|
|
|
|||
|
|
@ -31,36 +31,193 @@ type NFSClient struct {
|
|||
mountstatsPath string
|
||||
}
|
||||
|
||||
func convertToUint64(line []string) ([]uint64, error) {
|
||||
/* A "line" of input data (a pre-split array of strings) is
|
||||
processed one field at a time. Each field is converted to
|
||||
an uint64 value, and appended to an array of return values.
|
||||
On an error, check for ErrRange, and returns an error
|
||||
if found. This situation indicates a pretty major issue in
|
||||
the /proc/self/mountstats file, and returning faulty data
|
||||
is worse than no data. Other errors are ignored, and append
|
||||
whatever we got in the first place (probably 0).
|
||||
Yes, this is ugly. */
|
||||
func (*NFSClient) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
if len(line) < 2 {
|
||||
return nil, nil
|
||||
func (n *NFSClient) Init() error {
|
||||
var nfs3Fields = []string{
|
||||
"NULL",
|
||||
"GETATTR",
|
||||
"SETATTR",
|
||||
"LOOKUP",
|
||||
"ACCESS",
|
||||
"READLINK",
|
||||
"READ",
|
||||
"WRITE",
|
||||
"CREATE",
|
||||
"MKDIR",
|
||||
"SYMLINK",
|
||||
"MKNOD",
|
||||
"REMOVE",
|
||||
"RMDIR",
|
||||
"RENAME",
|
||||
"LINK",
|
||||
"READDIR",
|
||||
"READDIRPLUS",
|
||||
"FSSTAT",
|
||||
"FSINFO",
|
||||
"PATHCONF",
|
||||
"COMMIT",
|
||||
}
|
||||
|
||||
nline := make([]uint64, 0, len(line[1:]))
|
||||
// Skip the first field; it's handled specially as the "first" variable
|
||||
for _, l := range line[1:] {
|
||||
val, err := strconv.ParseUint(l, 10, 64)
|
||||
if err != nil {
|
||||
var numError *strconv.NumError
|
||||
if errors.As(err, &numError) {
|
||||
if errors.Is(numError.Err, strconv.ErrRange) {
|
||||
return nil, fmt.Errorf("errrange: line:[%v] raw:[%v] -> parsed:[%v]", line, l, val)
|
||||
}
|
||||
var nfs4Fields = []string{
|
||||
"NULL",
|
||||
"READ",
|
||||
"WRITE",
|
||||
"COMMIT",
|
||||
"OPEN",
|
||||
"OPEN_CONFIRM",
|
||||
"OPEN_NOATTR",
|
||||
"OPEN_DOWNGRADE",
|
||||
"CLOSE",
|
||||
"SETATTR",
|
||||
"FSINFO",
|
||||
"RENEW",
|
||||
"SETCLIENTID",
|
||||
"SETCLIENTID_CONFIRM",
|
||||
"LOCK",
|
||||
"LOCKT",
|
||||
"LOCKU",
|
||||
"ACCESS",
|
||||
"GETATTR",
|
||||
"LOOKUP",
|
||||
"LOOKUP_ROOT",
|
||||
"REMOVE",
|
||||
"RENAME",
|
||||
"LINK",
|
||||
"SYMLINK",
|
||||
"CREATE",
|
||||
"PATHCONF",
|
||||
"STATFS",
|
||||
"READLINK",
|
||||
"READDIR",
|
||||
"SERVER_CAPS",
|
||||
"DELEGRETURN",
|
||||
"GETACL",
|
||||
"SETACL",
|
||||
"FS_LOCATIONS",
|
||||
"RELEASE_LOCKOWNER",
|
||||
"SECINFO",
|
||||
"FSID_PRESENT",
|
||||
"EXCHANGE_ID",
|
||||
"CREATE_SESSION",
|
||||
"DESTROY_SESSION",
|
||||
"SEQUENCE",
|
||||
"GET_LEASE_TIME",
|
||||
"RECLAIM_COMPLETE",
|
||||
"LAYOUTGET",
|
||||
"GETDEVICEINFO",
|
||||
"LAYOUTCOMMIT",
|
||||
"LAYOUTRETURN",
|
||||
"SECINFO_NO_NAME",
|
||||
"TEST_STATEID",
|
||||
"FREE_STATEID",
|
||||
"GETDEVICELIST",
|
||||
"BIND_CONN_TO_SESSION",
|
||||
"DESTROY_CLIENTID",
|
||||
"SEEK",
|
||||
"ALLOCATE",
|
||||
"DEALLOCATE",
|
||||
"LAYOUTSTATS",
|
||||
"CLONE",
|
||||
"COPY",
|
||||
"OFFLOAD_CANCEL",
|
||||
"LOOKUPP",
|
||||
"LAYOUTERROR",
|
||||
"COPY_NOTIFY",
|
||||
"GETXATTR",
|
||||
"SETXATTR",
|
||||
"LISTXATTRS",
|
||||
"REMOVEXATTR",
|
||||
}
|
||||
|
||||
nfs3Ops := make(map[string]bool)
|
||||
nfs4Ops := make(map[string]bool)
|
||||
|
||||
n.mountstatsPath = n.getMountStatsPath()
|
||||
|
||||
if len(n.IncludeOperations) == 0 {
|
||||
for _, Op := range nfs3Fields {
|
||||
nfs3Ops[Op] = true
|
||||
}
|
||||
for _, Op := range nfs4Fields {
|
||||
nfs4Ops[Op] = true
|
||||
}
|
||||
} else {
|
||||
for _, Op := range n.IncludeOperations {
|
||||
nfs3Ops[Op] = true
|
||||
}
|
||||
for _, Op := range n.IncludeOperations {
|
||||
nfs4Ops[Op] = true
|
||||
}
|
||||
}
|
||||
|
||||
if len(n.ExcludeOperations) > 0 {
|
||||
for _, Op := range n.ExcludeOperations {
|
||||
if nfs3Ops[Op] {
|
||||
delete(nfs3Ops, Op)
|
||||
}
|
||||
if nfs4Ops[Op] {
|
||||
delete(nfs4Ops, Op)
|
||||
}
|
||||
}
|
||||
nline = append(nline, val)
|
||||
}
|
||||
return nline, nil
|
||||
|
||||
n.nfs3Ops = nfs3Ops
|
||||
n.nfs4Ops = nfs4Ops
|
||||
|
||||
if len(n.IncludeMounts) > 0 {
|
||||
n.Log.Debugf("Including these mount patterns: %v", n.IncludeMounts)
|
||||
} else {
|
||||
n.Log.Debugf("Including all mounts.")
|
||||
}
|
||||
|
||||
if len(n.ExcludeMounts) > 0 {
|
||||
n.Log.Debugf("Excluding these mount patterns: %v", n.ExcludeMounts)
|
||||
} else {
|
||||
n.Log.Debugf("Not excluding any mounts.")
|
||||
}
|
||||
|
||||
if len(n.IncludeOperations) > 0 {
|
||||
n.Log.Debugf("Including these operations: %v", n.IncludeOperations)
|
||||
} else {
|
||||
n.Log.Debugf("Including all operations.")
|
||||
}
|
||||
|
||||
if len(n.ExcludeOperations) > 0 {
|
||||
n.Log.Debugf("Excluding these mount patterns: %v", n.ExcludeOperations)
|
||||
} else {
|
||||
n.Log.Debugf("Not excluding any operations.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NFSClient) Gather(acc telegraf.Accumulator) error {
|
||||
if _, err := os.Stat(n.mountstatsPath); os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Attempt to read the file to see if we have permissions before opening
|
||||
// which can lead to a panic
|
||||
if _, err := os.ReadFile(n.mountstatsPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Open(n.mountstatsPath)
|
||||
if err != nil {
|
||||
n.Log.Errorf("Failed opening the %q file: %v ", file.Name(), err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
if err := n.processText(scanner, acc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
func (n *NFSClient) parseStat(mountpoint, export, version string, line []string, acc telegraf.Accumulator) error {
|
||||
|
|
@ -291,193 +448,36 @@ func (n *NFSClient) getMountStatsPath() string {
|
|||
return path
|
||||
}
|
||||
|
||||
func (*NFSClient) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
func convertToUint64(line []string) ([]uint64, error) {
|
||||
/* A "line" of input data (a pre-split array of strings) is
|
||||
processed one field at a time. Each field is converted to
|
||||
an uint64 value, and appended to an array of return values.
|
||||
On an error, check for ErrRange, and returns an error
|
||||
if found. This situation indicates a pretty major issue in
|
||||
the /proc/self/mountstats file, and returning faulty data
|
||||
is worse than no data. Other errors are ignored, and append
|
||||
whatever we got in the first place (probably 0).
|
||||
Yes, this is ugly. */
|
||||
|
||||
func (n *NFSClient) Gather(acc telegraf.Accumulator) error {
|
||||
if _, err := os.Stat(n.mountstatsPath); os.IsNotExist(err) {
|
||||
return err
|
||||
if len(line) < 2 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Attempt to read the file to see if we have permissions before opening
|
||||
// which can lead to a panic
|
||||
if _, err := os.ReadFile(n.mountstatsPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
file, err := os.Open(n.mountstatsPath)
|
||||
if err != nil {
|
||||
n.Log.Errorf("Failed opening the %q file: %v ", file.Name(), err)
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
if err := n.processText(scanner, acc); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return scanner.Err()
|
||||
}
|
||||
|
||||
func (n *NFSClient) Init() error {
|
||||
var nfs3Fields = []string{
|
||||
"NULL",
|
||||
"GETATTR",
|
||||
"SETATTR",
|
||||
"LOOKUP",
|
||||
"ACCESS",
|
||||
"READLINK",
|
||||
"READ",
|
||||
"WRITE",
|
||||
"CREATE",
|
||||
"MKDIR",
|
||||
"SYMLINK",
|
||||
"MKNOD",
|
||||
"REMOVE",
|
||||
"RMDIR",
|
||||
"RENAME",
|
||||
"LINK",
|
||||
"READDIR",
|
||||
"READDIRPLUS",
|
||||
"FSSTAT",
|
||||
"FSINFO",
|
||||
"PATHCONF",
|
||||
"COMMIT",
|
||||
}
|
||||
|
||||
var nfs4Fields = []string{
|
||||
"NULL",
|
||||
"READ",
|
||||
"WRITE",
|
||||
"COMMIT",
|
||||
"OPEN",
|
||||
"OPEN_CONFIRM",
|
||||
"OPEN_NOATTR",
|
||||
"OPEN_DOWNGRADE",
|
||||
"CLOSE",
|
||||
"SETATTR",
|
||||
"FSINFO",
|
||||
"RENEW",
|
||||
"SETCLIENTID",
|
||||
"SETCLIENTID_CONFIRM",
|
||||
"LOCK",
|
||||
"LOCKT",
|
||||
"LOCKU",
|
||||
"ACCESS",
|
||||
"GETATTR",
|
||||
"LOOKUP",
|
||||
"LOOKUP_ROOT",
|
||||
"REMOVE",
|
||||
"RENAME",
|
||||
"LINK",
|
||||
"SYMLINK",
|
||||
"CREATE",
|
||||
"PATHCONF",
|
||||
"STATFS",
|
||||
"READLINK",
|
||||
"READDIR",
|
||||
"SERVER_CAPS",
|
||||
"DELEGRETURN",
|
||||
"GETACL",
|
||||
"SETACL",
|
||||
"FS_LOCATIONS",
|
||||
"RELEASE_LOCKOWNER",
|
||||
"SECINFO",
|
||||
"FSID_PRESENT",
|
||||
"EXCHANGE_ID",
|
||||
"CREATE_SESSION",
|
||||
"DESTROY_SESSION",
|
||||
"SEQUENCE",
|
||||
"GET_LEASE_TIME",
|
||||
"RECLAIM_COMPLETE",
|
||||
"LAYOUTGET",
|
||||
"GETDEVICEINFO",
|
||||
"LAYOUTCOMMIT",
|
||||
"LAYOUTRETURN",
|
||||
"SECINFO_NO_NAME",
|
||||
"TEST_STATEID",
|
||||
"FREE_STATEID",
|
||||
"GETDEVICELIST",
|
||||
"BIND_CONN_TO_SESSION",
|
||||
"DESTROY_CLIENTID",
|
||||
"SEEK",
|
||||
"ALLOCATE",
|
||||
"DEALLOCATE",
|
||||
"LAYOUTSTATS",
|
||||
"CLONE",
|
||||
"COPY",
|
||||
"OFFLOAD_CANCEL",
|
||||
"LOOKUPP",
|
||||
"LAYOUTERROR",
|
||||
"COPY_NOTIFY",
|
||||
"GETXATTR",
|
||||
"SETXATTR",
|
||||
"LISTXATTRS",
|
||||
"REMOVEXATTR",
|
||||
}
|
||||
|
||||
nfs3Ops := make(map[string]bool)
|
||||
nfs4Ops := make(map[string]bool)
|
||||
|
||||
n.mountstatsPath = n.getMountStatsPath()
|
||||
|
||||
if len(n.IncludeOperations) == 0 {
|
||||
for _, Op := range nfs3Fields {
|
||||
nfs3Ops[Op] = true
|
||||
}
|
||||
for _, Op := range nfs4Fields {
|
||||
nfs4Ops[Op] = true
|
||||
}
|
||||
} else {
|
||||
for _, Op := range n.IncludeOperations {
|
||||
nfs3Ops[Op] = true
|
||||
}
|
||||
for _, Op := range n.IncludeOperations {
|
||||
nfs4Ops[Op] = true
|
||||
}
|
||||
}
|
||||
|
||||
if len(n.ExcludeOperations) > 0 {
|
||||
for _, Op := range n.ExcludeOperations {
|
||||
if nfs3Ops[Op] {
|
||||
delete(nfs3Ops, Op)
|
||||
}
|
||||
if nfs4Ops[Op] {
|
||||
delete(nfs4Ops, Op)
|
||||
nline := make([]uint64, 0, len(line[1:]))
|
||||
// Skip the first field; it's handled specially as the "first" variable
|
||||
for _, l := range line[1:] {
|
||||
val, err := strconv.ParseUint(l, 10, 64)
|
||||
if err != nil {
|
||||
var numError *strconv.NumError
|
||||
if errors.As(err, &numError) {
|
||||
if errors.Is(numError.Err, strconv.ErrRange) {
|
||||
return nil, fmt.Errorf("errrange: line:[%v] raw:[%v] -> parsed:[%v]", line, l, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
nline = append(nline, val)
|
||||
}
|
||||
|
||||
n.nfs3Ops = nfs3Ops
|
||||
n.nfs4Ops = nfs4Ops
|
||||
|
||||
if len(n.IncludeMounts) > 0 {
|
||||
n.Log.Debugf("Including these mount patterns: %v", n.IncludeMounts)
|
||||
} else {
|
||||
n.Log.Debugf("Including all mounts.")
|
||||
}
|
||||
|
||||
if len(n.ExcludeMounts) > 0 {
|
||||
n.Log.Debugf("Excluding these mount patterns: %v", n.ExcludeMounts)
|
||||
} else {
|
||||
n.Log.Debugf("Not excluding any mounts.")
|
||||
}
|
||||
|
||||
if len(n.IncludeOperations) > 0 {
|
||||
n.Log.Debugf("Including these operations: %v", n.IncludeOperations)
|
||||
} else {
|
||||
n.Log.Debugf("Including all operations.")
|
||||
}
|
||||
|
||||
if len(n.ExcludeOperations) > 0 {
|
||||
n.Log.Debugf("Excluding these mount patterns: %v", n.ExcludeOperations)
|
||||
} else {
|
||||
n.Log.Debugf("Not excluding any operations.")
|
||||
}
|
||||
|
||||
return nil
|
||||
return nline, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ import (
|
|||
var sampleConfig string
|
||||
|
||||
type Nginx struct {
|
||||
Urls []string
|
||||
ResponseTimeout config.Duration
|
||||
Urls []string `toml:"urls"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
tls.ClientConfig
|
||||
|
||||
// HTTP client
|
||||
|
|
|
|||
|
|
@ -276,11 +276,11 @@ func gatherStatusURL(r *bufio.Reader, tags map[string]string, acc telegraf.Accum
|
|||
if err := dec.Decode(status); err != nil {
|
||||
return errors.New("error while decoding JSON response")
|
||||
}
|
||||
status.Gather(tags, acc)
|
||||
status.gather(tags, acc)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *status) Gather(tags map[string]string, acc telegraf.Accumulator) {
|
||||
func (s *status) gather(tags map[string]string, acc telegraf.Accumulator) {
|
||||
s.gatherProcessesMetrics(tags, acc)
|
||||
s.gatherConnectionsMetrics(tags, acc)
|
||||
s.gatherSslMetrics(tags, acc)
|
||||
|
|
|
|||
|
|
@ -18,15 +18,6 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type NginxPlusAPI struct {
|
||||
Urls []string `toml:"urls"`
|
||||
APIVersion int64 `toml:"api_version"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
tls.ClientConfig
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
const (
|
||||
// Default settings
|
||||
defaultAPIVersion = 3
|
||||
|
|
@ -49,6 +40,15 @@ const (
|
|||
streamUpstreamsPath = "stream/upstreams"
|
||||
)
|
||||
|
||||
type NginxPlusAPI struct {
|
||||
Urls []string `toml:"urls"`
|
||||
APIVersion int64 `toml:"api_version"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
tls.ClientConfig
|
||||
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func (*NginxPlusAPI) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func (n *NginxSTS) gatherURL(addr *url.URL, acc telegraf.Accumulator) error {
|
|||
}
|
||||
}
|
||||
|
||||
type NginxSTSResponse struct {
|
||||
type nginxSTSResponse struct {
|
||||
Connections struct {
|
||||
Active uint64 `json:"active"`
|
||||
Reading uint64 `json:"reading"`
|
||||
|
|
@ -117,12 +117,12 @@ type NginxSTSResponse struct {
|
|||
Requests uint64 `json:"requests"`
|
||||
} `json:"connections"`
|
||||
Hostname string `json:"hostName"`
|
||||
StreamFilterZones map[string]map[string]Server `json:"streamFilterZones"`
|
||||
StreamServerZones map[string]Server `json:"streamServerZones"`
|
||||
StreamUpstreamZones map[string][]Upstream `json:"streamUpstreamZones"`
|
||||
StreamFilterZones map[string]map[string]server `json:"streamFilterZones"`
|
||||
StreamServerZones map[string]server `json:"streamServerZones"`
|
||||
StreamUpstreamZones map[string][]upstream `json:"streamUpstreamZones"`
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
type server struct {
|
||||
ConnectCounter uint64 `json:"connectCounter"`
|
||||
InBytes uint64 `json:"inBytes"`
|
||||
OutBytes uint64 `json:"outBytes"`
|
||||
|
|
@ -137,7 +137,7 @@ type Server struct {
|
|||
} `json:"responses"`
|
||||
}
|
||||
|
||||
type Upstream struct {
|
||||
type upstream struct {
|
||||
Server string `json:"server"`
|
||||
ConnectCounter uint64 `json:"connectCounter"`
|
||||
InBytes uint64 `json:"inBytes"`
|
||||
|
|
@ -166,7 +166,7 @@ type Upstream struct {
|
|||
|
||||
func gatherStatusURL(r *bufio.Reader, tags map[string]string, acc telegraf.Accumulator) error {
|
||||
dec := json.NewDecoder(r)
|
||||
status := &NginxSTSResponse{}
|
||||
status := &nginxSTSResponse{}
|
||||
if err := dec.Decode(status); err != nil {
|
||||
return errors.New("error while decoding JSON response")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,31 +34,15 @@ type NginxUpstreamCheck struct {
|
|||
client *http.Client
|
||||
}
|
||||
|
||||
func NewNginxUpstreamCheck() *NginxUpstreamCheck {
|
||||
return &NginxUpstreamCheck{
|
||||
URL: "http://127.0.0.1/status?format=json",
|
||||
Method: "GET",
|
||||
Headers: make(map[string]string),
|
||||
HostHeader: "",
|
||||
Timeout: config.Duration(time.Second * 5),
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nginx_upstream_check", func() telegraf.Input {
|
||||
return NewNginxUpstreamCheck()
|
||||
})
|
||||
}
|
||||
|
||||
type NginxUpstreamCheckData struct {
|
||||
type nginxUpstreamCheckData struct {
|
||||
Servers struct {
|
||||
Total uint64 `json:"total"`
|
||||
Generation uint64 `json:"generation"`
|
||||
Server []NginxUpstreamCheckServer `json:"server"`
|
||||
Server []nginxUpstreamCheckServer `json:"server"`
|
||||
} `json:"servers"`
|
||||
}
|
||||
|
||||
type NginxUpstreamCheckServer struct {
|
||||
type nginxUpstreamCheckServer struct {
|
||||
Index uint64 `json:"index"`
|
||||
Upstream string `json:"upstream"`
|
||||
Name string `json:"name"`
|
||||
|
|
@ -69,6 +53,33 @@ type NginxUpstreamCheckServer struct {
|
|||
Port uint16 `json:"port"`
|
||||
}
|
||||
|
||||
func (*NginxUpstreamCheck) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (check *NginxUpstreamCheck) Gather(accumulator telegraf.Accumulator) error {
|
||||
if check.client == nil {
|
||||
client, err := check.createHTTPClient()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
check.client = client
|
||||
}
|
||||
|
||||
statusURL, err := url.Parse(check.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = check.gatherStatusData(statusURL.String(), accumulator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// createHTTPClient create a clients to access API
|
||||
func (check *NginxUpstreamCheck) createHTTPClient() (*http.Client, error) {
|
||||
tlsConfig, err := check.ClientConfig.TLSConfig()
|
||||
|
|
@ -130,35 +141,8 @@ func (check *NginxUpstreamCheck) gatherJSONData(address string, value interface{
|
|||
return nil
|
||||
}
|
||||
|
||||
func (*NginxUpstreamCheck) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (check *NginxUpstreamCheck) Gather(accumulator telegraf.Accumulator) error {
|
||||
if check.client == nil {
|
||||
client, err := check.createHTTPClient()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
check.client = client
|
||||
}
|
||||
|
||||
statusURL, err := url.Parse(check.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = check.gatherStatusData(statusURL.String(), accumulator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (check *NginxUpstreamCheck) gatherStatusData(address string, accumulator telegraf.Accumulator) error {
|
||||
checkData := &NginxUpstreamCheckData{}
|
||||
checkData := &nginxUpstreamCheckData{}
|
||||
|
||||
err := check.gatherJSONData(address, checkData)
|
||||
if err != nil {
|
||||
|
|
@ -197,3 +181,19 @@ func (check *NginxUpstreamCheck) getStatusCode(status string) uint8 {
|
|||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func newNginxUpstreamCheck() *NginxUpstreamCheck {
|
||||
return &NginxUpstreamCheck{
|
||||
URL: "http://127.0.0.1/status?format=json",
|
||||
Method: "GET",
|
||||
Headers: make(map[string]string),
|
||||
HostHeader: "",
|
||||
Timeout: config.Duration(time.Second * 5),
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nginx_upstream_check", func() telegraf.Input {
|
||||
return newNginxUpstreamCheck()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ func TestNginxUpstreamCheckData(test *testing.T) {
|
|||
}))
|
||||
defer testServer.Close()
|
||||
|
||||
check := NewNginxUpstreamCheck()
|
||||
check := newNginxUpstreamCheck()
|
||||
check.URL = testServer.URL + "/status"
|
||||
|
||||
var accumulator testutil.Accumulator
|
||||
|
|
@ -139,7 +139,7 @@ func TestNginxUpstreamCheckRequest(test *testing.T) {
|
|||
}))
|
||||
defer testServer.Close()
|
||||
|
||||
check := NewNginxUpstreamCheck()
|
||||
check := newNginxUpstreamCheck()
|
||||
check.URL = testServer.URL + "/status"
|
||||
check.Headers["X-test"] = "test-value"
|
||||
check.HostHeader = "status.local"
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func (n *NginxVTS) gatherURL(addr *url.URL, acc telegraf.Accumulator) error {
|
|||
}
|
||||
}
|
||||
|
||||
type NginxVTSResponse struct {
|
||||
type nginxVTSResponse struct {
|
||||
Connections struct {
|
||||
Active uint64 `json:"active"`
|
||||
Reading uint64 `json:"reading"`
|
||||
|
|
@ -116,13 +116,13 @@ type NginxVTSResponse struct {
|
|||
Handled uint64 `json:"handled"`
|
||||
Requests uint64 `json:"requests"`
|
||||
} `json:"connections"`
|
||||
ServerZones map[string]Server `json:"serverZones"`
|
||||
FilterZones map[string]map[string]Server `json:"filterZones"`
|
||||
UpstreamZones map[string][]Upstream `json:"upstreamZones"`
|
||||
CacheZones map[string]Cache `json:"cacheZones"`
|
||||
ServerZones map[string]server `json:"serverZones"`
|
||||
FilterZones map[string]map[string]server `json:"filterZones"`
|
||||
UpstreamZones map[string][]upstream `json:"upstreamZones"`
|
||||
CacheZones map[string]cache `json:"cacheZones"`
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
type server struct {
|
||||
RequestCounter uint64 `json:"requestCounter"`
|
||||
InBytes uint64 `json:"inBytes"`
|
||||
OutBytes uint64 `json:"outBytes"`
|
||||
|
|
@ -144,7 +144,7 @@ type Server struct {
|
|||
} `json:"responses"`
|
||||
}
|
||||
|
||||
type Upstream struct {
|
||||
type upstream struct {
|
||||
Server string `json:"server"`
|
||||
RequestCounter uint64 `json:"requestCounter"`
|
||||
InBytes uint64 `json:"inBytes"`
|
||||
|
|
@ -165,7 +165,7 @@ type Upstream struct {
|
|||
Down bool `json:"down"`
|
||||
}
|
||||
|
||||
type Cache struct {
|
||||
type cache struct {
|
||||
MaxSize uint64 `json:"maxSize"`
|
||||
UsedSize uint64 `json:"usedSize"`
|
||||
InBytes uint64 `json:"inBytes"`
|
||||
|
|
@ -184,7 +184,7 @@ type Cache struct {
|
|||
|
||||
func gatherStatusURL(r *bufio.Reader, tags map[string]string, acc telegraf.Accumulator) error {
|
||||
dec := json.NewDecoder(r)
|
||||
status := &NginxVTSResponse{}
|
||||
status := &nginxVTSResponse{}
|
||||
if err := dec.Decode(status); err != nil {
|
||||
return errors.New("error while decoding JSON response")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,27 +18,16 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
// Nomad configuration object
|
||||
const timeLayout = "2006-01-02 15:04:05 -0700 MST"
|
||||
|
||||
type Nomad struct {
|
||||
URL string `toml:"url"`
|
||||
|
||||
URL string `toml:"url"`
|
||||
ResponseTimeout config.Duration `toml:"response_timeout"`
|
||||
|
||||
tls.ClientConfig
|
||||
|
||||
roundTripper http.RoundTripper
|
||||
}
|
||||
|
||||
const timeLayout = "2006-01-02 15:04:05 -0700 MST"
|
||||
|
||||
func init() {
|
||||
inputs.Add("nomad", func() telegraf.Input {
|
||||
return &Nomad{
|
||||
ResponseTimeout: config.Duration(5 * time.Second),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (*Nomad) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
|
@ -161,3 +150,11 @@ func buildNomadMetrics(acc telegraf.Accumulator, summaryMetrics *metricsSummary)
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nomad", func() telegraf.Input {
|
||||
return &Nomad{
|
||||
ResponseTimeout: config.Duration(5 * time.Second),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ type sampledValue struct {
|
|||
DisplayLabels map[string]string `json:"Labels"`
|
||||
}
|
||||
|
||||
// AggregateSample needs to be exported, because JSON decode cannot set embedded pointer to unexported struct
|
||||
type AggregateSample struct {
|
||||
Count int `json:"count"`
|
||||
Rate float64 `json:"rate"`
|
||||
|
|
|
|||
|
|
@ -21,61 +21,27 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type runner func(cmdName string, timeout config.Duration, useSudo bool, Server string, ConfigFile string) (*bytes.Buffer, error)
|
||||
var (
|
||||
defaultBinary = "/usr/sbin/nsd-control"
|
||||
defaultTimeout = config.Duration(time.Second)
|
||||
)
|
||||
|
||||
// NSD is used to store configuration values
|
||||
type NSD struct {
|
||||
Binary string
|
||||
Timeout config.Duration
|
||||
UseSudo bool
|
||||
Server string
|
||||
ConfigFile string
|
||||
Binary string `toml:"binary"`
|
||||
Timeout config.Duration `toml:"timeout"`
|
||||
UseSudo bool `toml:"use_sudo"`
|
||||
Server string `toml:"server"`
|
||||
ConfigFile string `toml:"config_file"`
|
||||
|
||||
run runner
|
||||
}
|
||||
|
||||
var defaultBinary = "/usr/sbin/nsd-control"
|
||||
var defaultTimeout = config.Duration(time.Second)
|
||||
|
||||
// Shell out to nsd_stat and return the output
|
||||
func nsdRunner(cmdName string, timeout config.Duration, useSudo bool, server, configFile string) (*bytes.Buffer, error) {
|
||||
cmdArgs := []string{"stats_noreset"}
|
||||
|
||||
if server != "" {
|
||||
host, port, err := net.SplitHostPort(server)
|
||||
if err == nil {
|
||||
server = host + "@" + port
|
||||
}
|
||||
|
||||
cmdArgs = append([]string{"-s", server}, cmdArgs...)
|
||||
}
|
||||
|
||||
if configFile != "" {
|
||||
cmdArgs = append([]string{"-c", configFile}, cmdArgs...)
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdName, cmdArgs...)
|
||||
|
||||
if useSudo {
|
||||
cmdArgs = append([]string{cmdName}, cmdArgs...)
|
||||
cmd = exec.Command("sudo", cmdArgs...)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := internal.RunTimeout(cmd, time.Duration(timeout))
|
||||
if err != nil {
|
||||
return &out, fmt.Errorf("error running nsd-control: %w (%s %v)", err, cmdName, cmdArgs)
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
type runner func(cmdName string, timeout config.Duration, useSudo bool, Server string, ConfigFile string) (*bytes.Buffer, error)
|
||||
|
||||
func (*NSD) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
// Gather collects stats from nsd-control and adds them to the Accumulator
|
||||
func (s *NSD) Gather(acc telegraf.Accumulator) error {
|
||||
out, err := s.run(s.Binary, s.Timeout, s.UseSudo, s.Server, s.ConfigFile)
|
||||
if err != nil {
|
||||
|
|
@ -133,6 +99,40 @@ func (s *NSD) Gather(acc telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Shell out to nsd_stat and return the output
|
||||
func nsdRunner(cmdName string, timeout config.Duration, useSudo bool, server, configFile string) (*bytes.Buffer, error) {
|
||||
cmdArgs := []string{"stats_noreset"}
|
||||
|
||||
if server != "" {
|
||||
host, port, err := net.SplitHostPort(server)
|
||||
if err == nil {
|
||||
server = host + "@" + port
|
||||
}
|
||||
|
||||
cmdArgs = append([]string{"-s", server}, cmdArgs...)
|
||||
}
|
||||
|
||||
if configFile != "" {
|
||||
cmdArgs = append([]string{"-c", configFile}, cmdArgs...)
|
||||
}
|
||||
|
||||
cmd := exec.Command(cmdName, cmdArgs...)
|
||||
|
||||
if useSudo {
|
||||
cmdArgs = append([]string{cmdName}, cmdArgs...)
|
||||
cmd = exec.Command("sudo", cmdArgs...)
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := internal.RunTimeout(cmd, time.Duration(timeout))
|
||||
if err != nil {
|
||||
return &out, fmt.Errorf("error running nsd-control: %w (%s %v)", err, cmdName, cmdArgs)
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nsd", func() telegraf.Input {
|
||||
return &NSD{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"github.com/influxdata/telegraf/testutil"
|
||||
)
|
||||
|
||||
func NSDControl(output string) func(string, config.Duration, bool, string, string) (*bytes.Buffer, error) {
|
||||
func nsdControl(output string) func(string, config.Duration, bool, string, string) (*bytes.Buffer, error) {
|
||||
return func(string, config.Duration, bool, string, string) (*bytes.Buffer, error) {
|
||||
return bytes.NewBufferString(output), nil
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ func NSDControl(output string) func(string, config.Duration, bool, string, strin
|
|||
func TestParseFullOutput(t *testing.T) {
|
||||
acc := &testutil.Accumulator{}
|
||||
v := &NSD{
|
||||
run: NSDControl(fullOutput),
|
||||
run: nsdControl(fullOutput),
|
||||
}
|
||||
err := v.Gather(acc)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,25 +42,15 @@ import (
|
|||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
// Might add Lookupd endpoints for cluster discovery
|
||||
type NSQ struct {
|
||||
Endpoints []string
|
||||
tls.ClientConfig
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
const (
|
||||
requestPattern = `%s/stats?format=json`
|
||||
)
|
||||
|
||||
func init() {
|
||||
inputs.Add("nsq", func() telegraf.Input {
|
||||
return New()
|
||||
})
|
||||
}
|
||||
type NSQ struct {
|
||||
Endpoints []string `toml:"endpoints"`
|
||||
|
||||
func New() *NSQ {
|
||||
return &NSQ{}
|
||||
tls.ClientConfig
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
func (*NSQ) SampleConfig() string {
|
||||
|
|
@ -305,3 +295,13 @@ type clientStats struct {
|
|||
TLSNegotiatedProtocol string `json:"tls_negotiated_protocol"`
|
||||
TLSNegotiatedProtocolIsMutual bool `json:"tls_negotiated_protocol_is_mutual"`
|
||||
}
|
||||
|
||||
func newNSQ() *NSQ {
|
||||
return &NSQ{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("nsq", func() telegraf.Input {
|
||||
return newNSQ()
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func TestNSQStatsV1(t *testing.T) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
n := New()
|
||||
n := newNSQ()
|
||||
n.Endpoints = []string{ts.URL}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
|
@ -283,7 +283,7 @@ func TestNSQStatsPreV1(t *testing.T) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
n := New()
|
||||
n := newNSQ()
|
||||
n.Endpoints = []string{ts.URL}
|
||||
|
||||
var acc testutil.Accumulator
|
||||
|
|
|
|||
|
|
@ -20,8 +20,29 @@ const (
|
|||
defaultMaxUndeliveredMessages = 1000
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
type semaphore chan empty
|
||||
type NSQConsumer struct {
|
||||
Server string `toml:"server" deprecated:"1.5.0;1.35.0;use 'nsqd' instead"`
|
||||
Nsqd []string `toml:"nsqd"`
|
||||
Nsqlookupd []string `toml:"nsqlookupd"`
|
||||
Topic string `toml:"topic"`
|
||||
Channel string `toml:"channel"`
|
||||
MaxInFlight int `toml:"max_in_flight"`
|
||||
MaxUndeliveredMessages int `toml:"max_undelivered_messages"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
parser telegraf.Parser
|
||||
consumer *nsq.Consumer
|
||||
|
||||
mu sync.Mutex
|
||||
messages map[telegraf.TrackingID]*nsq.Message
|
||||
wg sync.WaitGroup
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
type (
|
||||
empty struct{}
|
||||
semaphore chan empty
|
||||
)
|
||||
|
||||
type logger struct {
|
||||
log telegraf.Logger
|
||||
|
|
@ -32,28 +53,6 @@ func (l *logger) Output(_ int, s string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// NSQConsumer represents the configuration of the plugin
|
||||
type NSQConsumer struct {
|
||||
Server string `toml:"server" deprecated:"1.5.0;1.35.0;use 'nsqd' instead"`
|
||||
Nsqd []string `toml:"nsqd"`
|
||||
Nsqlookupd []string `toml:"nsqlookupd"`
|
||||
Topic string `toml:"topic"`
|
||||
Channel string `toml:"channel"`
|
||||
MaxInFlight int `toml:"max_in_flight"`
|
||||
|
||||
MaxUndeliveredMessages int `toml:"max_undelivered_messages"`
|
||||
|
||||
parser telegraf.Parser
|
||||
consumer *nsq.Consumer
|
||||
|
||||
Log telegraf.Logger
|
||||
|
||||
mu sync.Mutex
|
||||
messages map[telegraf.TrackingID]*nsq.Message
|
||||
wg sync.WaitGroup
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (*NSQConsumer) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
|
@ -77,7 +76,6 @@ func (n *NSQConsumer) SetParser(parser telegraf.Parser) {
|
|||
n.parser = parser
|
||||
}
|
||||
|
||||
// Start pulls data from nsq
|
||||
func (n *NSQConsumer) Start(ac telegraf.Accumulator) error {
|
||||
acc := ac.WithTracking(n.MaxUndeliveredMessages)
|
||||
sem := make(semaphore, n.MaxUndeliveredMessages)
|
||||
|
|
@ -140,6 +138,17 @@ func (n *NSQConsumer) Start(ac telegraf.Accumulator) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NSQConsumer) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NSQConsumer) Stop() {
|
||||
n.cancel()
|
||||
n.wg.Wait()
|
||||
n.consumer.Stop()
|
||||
<-n.consumer.StopChan
|
||||
}
|
||||
|
||||
func (n *NSQConsumer) onDelivery(ctx context.Context, acc telegraf.TrackingAccumulator, sem semaphore) {
|
||||
for {
|
||||
select {
|
||||
|
|
@ -165,19 +174,6 @@ func (n *NSQConsumer) onDelivery(ctx context.Context, acc telegraf.TrackingAccum
|
|||
}
|
||||
}
|
||||
|
||||
// Stop processing messages
|
||||
func (n *NSQConsumer) Stop() {
|
||||
n.cancel()
|
||||
n.wg.Wait()
|
||||
n.consumer.Stop()
|
||||
<-n.consumer.StopChan
|
||||
}
|
||||
|
||||
// Gather is a noop
|
||||
func (n *NSQConsumer) Gather(_ telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *NSQConsumer) connect() error {
|
||||
if n.consumer == nil {
|
||||
config := nsq.NewConfig()
|
||||
|
|
|
|||
|
|
@ -20,20 +20,18 @@ var (
|
|||
colonByte = []byte(":")
|
||||
)
|
||||
|
||||
// default file paths
|
||||
const (
|
||||
NetNetstat = "/net/netstat"
|
||||
NetSnmp = "/net/snmp"
|
||||
NetSnmp6 = "/net/snmp6"
|
||||
NetProc = "/proc"
|
||||
)
|
||||
// default file paths
|
||||
netNetstat = "/net/netstat"
|
||||
netSnmp = "/net/snmp"
|
||||
netSnmp6 = "/net/snmp6"
|
||||
netProc = "/proc"
|
||||
|
||||
// env variable names
|
||||
const (
|
||||
EnvNetstat = "PROC_NET_NETSTAT"
|
||||
EnvSnmp = "PROC_NET_SNMP"
|
||||
EnvSnmp6 = "PROC_NET_SNMP6"
|
||||
EnvRoot = "PROC_ROOT"
|
||||
// env variable names
|
||||
envNetstat = "PROC_NET_NETSTAT"
|
||||
envSnmp = "PROC_NET_SNMP"
|
||||
envSnmp6 = "PROC_NET_SNMP6"
|
||||
envRoot = "PROC_ROOT"
|
||||
)
|
||||
|
||||
type Nstat struct {
|
||||
|
|
@ -104,13 +102,13 @@ func (ns *Nstat) gatherSNMP6(data []byte, acc telegraf.Accumulator) {
|
|||
// if it is empty then try read from env variables
|
||||
func (ns *Nstat) loadPaths() {
|
||||
if ns.ProcNetNetstat == "" {
|
||||
ns.ProcNetNetstat = proc(EnvNetstat, NetNetstat)
|
||||
ns.ProcNetNetstat = proc(envNetstat, netNetstat)
|
||||
}
|
||||
if ns.ProcNetSNMP == "" {
|
||||
ns.ProcNetSNMP = proc(EnvSnmp, NetSnmp)
|
||||
ns.ProcNetSNMP = proc(envSnmp, netSnmp)
|
||||
}
|
||||
if ns.ProcNetSNMP6 == "" {
|
||||
ns.ProcNetSNMP6 = proc(EnvSnmp6, NetSnmp6)
|
||||
ns.ProcNetSNMP6 = proc(envSnmp6, netSnmp6)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,9 +186,9 @@ func proc(env, path string) string {
|
|||
return p
|
||||
}
|
||||
// try to read root path, or use default root path
|
||||
root := os.Getenv(EnvRoot)
|
||||
root := os.Getenv(envRoot)
|
||||
if root == "" {
|
||||
root = NetProc
|
||||
root = netProc
|
||||
}
|
||||
return root + path
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,16 +30,25 @@ var reBrackets = regexp.MustCompile(`\s+\([\S]*`)
|
|||
type elementType int64
|
||||
|
||||
const (
|
||||
None elementType = iota
|
||||
Tag
|
||||
FieldFloat
|
||||
FieldDuration
|
||||
FieldIntDecimal
|
||||
FieldIntOctal
|
||||
FieldIntRatio8
|
||||
FieldIntBits
|
||||
none elementType = iota
|
||||
tag
|
||||
fieldFloat
|
||||
fieldDuration
|
||||
fieldIntDecimal
|
||||
fieldIntOctal
|
||||
fieldIntRatio8
|
||||
fieldIntBits
|
||||
)
|
||||
|
||||
type NTPQ struct {
|
||||
DNSLookup bool `toml:"dns_lookup" deprecated:"1.24.0;1.35.0;add '-n' to 'options' instead to skip DNS lookup"`
|
||||
Options string `toml:"options"`
|
||||
Servers []string `toml:"servers"`
|
||||
ReachFormat string `toml:"reach_format"`
|
||||
|
||||
runQ func(string) ([]byte, error)
|
||||
}
|
||||
|
||||
type column struct {
|
||||
name string
|
||||
etype elementType
|
||||
|
|
@ -55,21 +64,12 @@ var tagHeaders = map[string]string{
|
|||
|
||||
// Mapping of fields
|
||||
var fieldElements = map[string]elementType{
|
||||
"delay": FieldFloat,
|
||||
"jitter": FieldFloat,
|
||||
"offset": FieldFloat,
|
||||
"reach": FieldIntDecimal,
|
||||
"poll": FieldDuration,
|
||||
"when": FieldDuration,
|
||||
}
|
||||
|
||||
type NTPQ struct {
|
||||
DNSLookup bool `toml:"dns_lookup" deprecated:"1.24.0;1.35.0;add '-n' to 'options' instead to skip DNS lookup"`
|
||||
Options string `toml:"options"`
|
||||
Servers []string `toml:"servers"`
|
||||
ReachFormat string `toml:"reach_format"`
|
||||
|
||||
runQ func(string) ([]byte, error)
|
||||
"delay": fieldFloat,
|
||||
"jitter": fieldFloat,
|
||||
"offset": fieldFloat,
|
||||
"reach": fieldIntDecimal,
|
||||
"poll": fieldDuration,
|
||||
"when": fieldDuration,
|
||||
}
|
||||
|
||||
func (*NTPQ) SampleConfig() string {
|
||||
|
|
@ -117,19 +117,19 @@ func (n *NTPQ) Init() error {
|
|||
n.ReachFormat = "octal"
|
||||
// Interpret the field as decimal integer returning
|
||||
// the raw (octal) representation
|
||||
fieldElements["reach"] = FieldIntDecimal
|
||||
fieldElements["reach"] = fieldIntDecimal
|
||||
case "decimal":
|
||||
// Interpret the field as octal integer returning
|
||||
// decimal number representation
|
||||
fieldElements["reach"] = FieldIntOctal
|
||||
fieldElements["reach"] = fieldIntOctal
|
||||
case "count":
|
||||
// Interpret the field as bits set returning
|
||||
// the number of bits set
|
||||
fieldElements["reach"] = FieldIntBits
|
||||
fieldElements["reach"] = fieldIntBits
|
||||
case "ratio":
|
||||
// Interpret the field as ratio between the number of
|
||||
// bits set and the maximum available bits set (8).
|
||||
fieldElements["reach"] = FieldIntRatio8
|
||||
fieldElements["reach"] = fieldIntRatio8
|
||||
default:
|
||||
return fmt.Errorf("unknown 'reach_format' %q", n.ReachFormat)
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ func (n *NTPQ) gatherServer(acc telegraf.Accumulator, server string) {
|
|||
if name, isTag := tagHeaders[el]; isTag {
|
||||
columns = append(columns, column{
|
||||
name: name,
|
||||
etype: Tag,
|
||||
etype: tag,
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ func (n *NTPQ) gatherServer(acc telegraf.Accumulator, server string) {
|
|||
}
|
||||
|
||||
// Skip the column if not found
|
||||
columns = append(columns, column{etype: None})
|
||||
columns = append(columns, column{etype: none})
|
||||
}
|
||||
break
|
||||
}
|
||||
|
|
@ -221,11 +221,11 @@ func (n *NTPQ) gatherServer(acc telegraf.Accumulator, server string) {
|
|||
col := columns[i]
|
||||
|
||||
switch col.etype {
|
||||
case None:
|
||||
case none:
|
||||
continue
|
||||
case Tag:
|
||||
case tag:
|
||||
tags[col.name] = raw
|
||||
case FieldFloat:
|
||||
case fieldFloat:
|
||||
value, err := strconv.ParseFloat(raw, 64)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("%sparsing %q (%v) as float failed", msgPrefix, col.name, raw)
|
||||
|
|
@ -233,7 +233,7 @@ func (n *NTPQ) gatherServer(acc telegraf.Accumulator, server string) {
|
|||
continue
|
||||
}
|
||||
fields[col.name] = value
|
||||
case FieldDuration:
|
||||
case fieldDuration:
|
||||
// Ignore fields only containing a minus
|
||||
if raw == "-" {
|
||||
continue
|
||||
|
|
@ -257,28 +257,28 @@ func (n *NTPQ) gatherServer(acc telegraf.Accumulator, server string) {
|
|||
continue
|
||||
}
|
||||
fields[col.name] = value * factor
|
||||
case FieldIntDecimal:
|
||||
case fieldIntDecimal:
|
||||
value, err := strconv.ParseInt(raw, 10, 64)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("parsing %q (%v) as int failed: %w", col.name, raw, err))
|
||||
continue
|
||||
}
|
||||
fields[col.name] = value
|
||||
case FieldIntOctal:
|
||||
case fieldIntOctal:
|
||||
value, err := strconv.ParseInt(raw, 8, 64)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("parsing %q (%v) as int failed: %w", col.name, raw, err))
|
||||
continue
|
||||
}
|
||||
fields[col.name] = value
|
||||
case FieldIntBits:
|
||||
case fieldIntBits:
|
||||
value, err := strconv.ParseUint(raw, 8, 64)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("parsing %q (%v) as int failed: %w", col.name, raw, err))
|
||||
continue
|
||||
}
|
||||
fields[col.name] = bits.OnesCount64(value)
|
||||
case FieldIntRatio8:
|
||||
case fieldIntRatio8:
|
||||
value, err := strconv.ParseUint(raw, 8, 64)
|
||||
if err != nil {
|
||||
acc.AddError(fmt.Errorf("parsing %q (%v) as int failed: %w", col.name, raw, err))
|
||||
|
|
|
|||
|
|
@ -5,12 +5,14 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// SetTagIfUsed sets those tags whose value is different from empty string.
|
||||
func SetTagIfUsed(m map[string]string, k, v string) {
|
||||
if v != "" {
|
||||
m[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// SetIfUsed sets those fields whose value is different from empty string.
|
||||
func SetIfUsed(t string, m map[string]interface{}, k, v string) {
|
||||
vals := strings.Fields(v)
|
||||
if len(vals) < 1 {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/influxdata/telegraf/plugins/inputs/nvidia_smi/common"
|
||||
)
|
||||
|
||||
// Parse parses the XML-encoded data from nvidia-smi and adds measurements.
|
||||
func Parse(acc telegraf.Accumulator, buf []byte) error {
|
||||
var s smi
|
||||
if err := xml.Unmarshal(buf, &s); err != nil {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"github.com/influxdata/telegraf/plugins/inputs/nvidia_smi/common"
|
||||
)
|
||||
|
||||
// Parse parses the XML-encoded data from nvidia-smi and adds measurements.
|
||||
func Parse(acc telegraf.Accumulator, buf []byte) error {
|
||||
var s smi
|
||||
if err := xml.Unmarshal(buf, &s); err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue