Created
December 20, 2016 11:33
-
-
Save jumping/e50932eca957ba5517c5ddb00e1ddc53 to your computer and use it in GitHub Desktop.
added the details of listening tcp port, the original file comes from https://github.com/prometheus/node_exporter/blob/master/collector/tcpstat_linux.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Copyright 2015 The Prometheus Authors | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
// +build !notcpstat | |
package collector | |
import ( | |
"bufio" | |
"fmt" | |
"io" | |
"os" | |
"strconv" | |
"strings" | |
"github.com/prometheus/client_golang/prometheus" | |
) | |
type TCPConnectionState int | |
type tcpStatCollector struct { | |
state *prometheus.Desc | |
listen *prometheus.Desc | |
} | |
const ( | |
TCP_ESTABLISHED TCPConnectionState = iota + 1 | |
TCP_SYN_SENT | |
TCP_SYN_RECV | |
TCP_FIN_WAIT1 | |
TCP_FIN_WAIT2 | |
TCP_TIME_WAIT | |
TCP_CLOSE | |
TCP_CLOSE_WAIT | |
TCP_LAST_ACK | |
TCP_LISTEN | |
TCP_CLOSING | |
) | |
func init() { | |
Factories["tcpstat"] = NewTCPStatCollector | |
} | |
// NewTCPStatCollector takes a returns | |
// a new Collector exposing network stats. | |
func NewTCPStatCollector() (Collector, error) { | |
return &tcpStatCollector{ | |
state: prometheus.NewDesc( | |
prometheus.BuildFQName(Namespace, "", "tcp_state"), | |
"Number of connection states.", | |
[]string{"state"}, nil, | |
), | |
listen: prometheus.NewDesc( | |
prometheus.BuildFQName(Namespace, "", "tcp_listen_state"), | |
"tcp listen states.", | |
[]string{"port"}, nil, | |
), | |
}, nil | |
} | |
func (c *tcpStatCollector) Update(ch chan<- prometheus.Metric) (err error) { | |
tcpStats, ports, err := getTCPStats(procFilePath("net/tcp")) | |
if err != nil { | |
return fmt.Errorf("couldn't get tcpstats: %s", err) | |
} | |
// if enabled ipv6 system | |
tcp6File := procFilePath("net/tcp6") | |
if _, hasIPv6 := os.Stat(tcp6File); hasIPv6 == nil { | |
tcp6Stats, tcp6ports, err := getTCPStats(tcp6File) | |
if err != nil { | |
return fmt.Errorf("couldn't get tcp6stats: %s", err) | |
} | |
for st, value := range tcp6Stats { | |
tcpStats[st] += value | |
} | |
for st, _ := range tcp6ports { | |
ports[st] = 1 | |
} | |
} | |
for st, value := range tcpStats { | |
name := st.String() | |
ch <- prometheus.MustNewConstMetric(c.state, prometheus.GaugeValue, value, name) | |
} | |
for st, value := range ports { | |
name := strconv.FormatInt(st, 10) | |
ch <- prometheus.MustNewConstMetric(c.listen, prometheus.GaugeValue, float64(value), name) | |
} | |
return err | |
} | |
func getTCPStats(statsFile string) (map[TCPConnectionState]float64, map[int64]int, error) { | |
file, err := os.Open(statsFile) | |
if err != nil { | |
return nil, nil, err | |
} | |
defer file.Close() | |
return parseTCPStats(file) | |
} | |
func parseTCPStats(r io.Reader) (map[TCPConnectionState]float64, map[int64]int, error) { | |
var ( | |
tcpStats = map[TCPConnectionState]float64{} | |
scanner = bufio.NewScanner(r) | |
ports = make(map[int64]int) | |
) | |
for scanner.Scan() { | |
parts := strings.Fields(scanner.Text()) | |
if len(parts) == 0 { | |
continue | |
} | |
if strings.HasPrefix(parts[0], "sl") { | |
continue | |
} | |
st, err := strconv.ParseInt(parts[3], 16, 8) | |
if err != nil { | |
return nil, nil, err | |
} | |
if st == 10 { | |
part := strings.Split(parts[1], ":") | |
pt, _ := strconv.ParseInt(part[1], 16, 16) | |
ports[pt] = 1 | |
} | |
tcpStats[TCPConnectionState(st)]++ | |
} | |
return tcpStats, ports, nil | |
} | |
func (st TCPConnectionState) String() string { | |
switch st { | |
case TCP_ESTABLISHED: | |
return "established" | |
case TCP_SYN_SENT: | |
return "syn_sent" | |
case TCP_SYN_RECV: | |
return "syn_recv" | |
case TCP_FIN_WAIT1: | |
return "fin_wait1" | |
case TCP_FIN_WAIT2: | |
return "fin_wait2" | |
case TCP_TIME_WAIT: | |
return "time_wait" | |
case TCP_CLOSE: | |
return "close" | |
case TCP_CLOSE_WAIT: | |
return "close_wait" | |
case TCP_LAST_ACK: | |
return "last_ack" | |
case TCP_LISTEN: | |
return "listen" | |
case TCP_CLOSING: | |
return "closing" | |
default: | |
return "unknown" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment