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 }