github.com/netdata/go.d.plugin@v0.58.1/modules/portcheck/collect.go (about)

     1  // SPDX-License-Identifier: GPL-3.0-or-later
     2  
     3  package portcheck
     4  
     5  import (
     6  	"fmt"
     7  	"sync"
     8  	"time"
     9  )
    10  
    11  type checkState string
    12  
    13  const (
    14  	checkStateSuccess checkState = "success"
    15  	checkStateTimeout checkState = "timeout"
    16  	checkStateFailed  checkState = "failed"
    17  )
    18  
    19  func (pc *PortCheck) collect() (map[string]int64, error) {
    20  	wg := &sync.WaitGroup{}
    21  
    22  	for _, p := range pc.ports {
    23  		wg.Add(1)
    24  		go func(p *port) { pc.checkPort(p); wg.Done() }(p)
    25  	}
    26  	wg.Wait()
    27  
    28  	mx := make(map[string]int64)
    29  
    30  	for _, p := range pc.ports {
    31  		mx[fmt.Sprintf("port_%d_current_state_duration", p.number)] = int64(p.inState)
    32  		mx[fmt.Sprintf("port_%d_latency", p.number)] = int64(p.latency)
    33  		mx[fmt.Sprintf("port_%d_%s", p.number, checkStateSuccess)] = 0
    34  		mx[fmt.Sprintf("port_%d_%s", p.number, checkStateTimeout)] = 0
    35  		mx[fmt.Sprintf("port_%d_%s", p.number, checkStateFailed)] = 0
    36  		mx[fmt.Sprintf("port_%d_%s", p.number, p.state)] = 1
    37  	}
    38  
    39  	return mx, nil
    40  }
    41  
    42  func (pc *PortCheck) checkPort(p *port) {
    43  	start := time.Now()
    44  	conn, err := pc.dial("tcp", fmt.Sprintf("%s:%d", pc.Host, p.number), pc.Timeout.Duration)
    45  	dur := time.Since(start)
    46  
    47  	defer func() {
    48  		if conn != nil {
    49  			_ = conn.Close()
    50  		}
    51  	}()
    52  
    53  	if err != nil {
    54  		v, ok := err.(interface{ Timeout() bool })
    55  		if ok && v.Timeout() {
    56  			pc.setPortState(p, checkStateTimeout)
    57  		} else {
    58  			pc.setPortState(p, checkStateFailed)
    59  		}
    60  		return
    61  	}
    62  	pc.setPortState(p, checkStateSuccess)
    63  	p.latency = durationToMs(dur)
    64  }
    65  
    66  func (pc *PortCheck) setPortState(p *port, s checkState) {
    67  	if p.state != s {
    68  		p.inState = pc.UpdateEvery
    69  		p.state = s
    70  	} else {
    71  		p.inState += pc.UpdateEvery
    72  	}
    73  }
    74  
    75  func durationToMs(duration time.Duration) int {
    76  	return int(duration) / (int(time.Millisecond) / int(time.Nanosecond))
    77  }