bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/scollector/collectors/network_windows.go (about)

     1  package collectors
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"regexp"
     7  	"strings"
     8  	"time"
     9  
    10  	"bosun.org/metadata"
    11  	"bosun.org/opentsdb"
    12  	"bosun.org/slog"
    13  	"github.com/StackExchange/wmi"
    14  )
    15  
    16  func init() {
    17  	collectors = append(collectors, &IntervalCollector{F: c_network_windows, init: winNetworkInit})
    18  
    19  	c_winnetteam := &IntervalCollector{
    20  		F: c_network_team_windows,
    21  	}
    22  	// Make sure MSFT_NetImPlatAdapter and MSFT_NetAdapterStatisticsSettingData
    23  	// are valid WMI classes when initializing c_network_team_windows
    24  	c_winnetteam.init = func() {
    25  		var dstTeamNic []MSFT_NetLbfoTeamNic
    26  		var dstStats []MSFT_NetAdapterStatisticsSettingData
    27  		queryTeamAdapter = wmi.CreateQuery(&dstTeamNic, "")
    28  		queryTeamStats = wmi.CreateQuery(&dstStats, "")
    29  		c_winnetteam.Enable = func() bool {
    30  			errTeamNic := queryWmiNamespace(queryTeamAdapter, &dstTeamNic, namespaceStandardCimv2)
    31  			errStats := queryWmiNamespace(queryTeamStats, &dstStats, namespaceStandardCimv2)
    32  			result := errTeamNic == nil && errStats == nil
    33  			return result
    34  		}
    35  	}
    36  	collectors = append(collectors, c_winnetteam)
    37  	c := &IntervalCollector{
    38  		F: c_network_windows_tcp,
    39  	}
    40  	c.init = wmiInit(c, func() interface{} { return &[]Win32_PerfRawData_Tcpip_TCPv4{} }, "", &winNetTCPQuery)
    41  	collectors = append(collectors, c)
    42  }
    43  
    44  var (
    45  	queryTeamStats         string
    46  	queryTeamAdapter       string
    47  	winNetTCPQuery         string
    48  	namespaceStandardCimv2 = "root\\StandardCimv2"
    49  	interfaceExclusions    = regexp.MustCompile("isatap|Teredo")
    50  
    51  	// instanceNameToUnderscore matches '#' '/' and '\' for replacing with '_'.
    52  	instanceNameToUnderscore         = regexp.MustCompile("[#/\\\\]")
    53  	mNicInstanceNameToInterfaceIndex = make(map[string]string)
    54  )
    55  
    56  // winNetworkToInstanceName converts a Network Adapter Name to the InstanceName
    57  // that is used in Win32_PerfRawData_Tcpip_NetworkInterface.
    58  func winNetworkToInstanceName(Name string) string {
    59  	instanceName := Name
    60  	instanceName = strings.Replace(instanceName, "(", "[", -1)
    61  	instanceName = strings.Replace(instanceName, ")", "]", -1)
    62  	instanceName = instanceNameToUnderscore.ReplaceAllString(instanceName, "_")
    63  	return instanceName
    64  }
    65  
    66  // winNetworkInit maintains a mapping of InstanceName to InterfaceIndex
    67  func winNetworkInit() {
    68  	update := func() {
    69  		var dstNetworkAdapter []Win32_NetworkAdapter
    70  		q := wmi.CreateQuery(&dstNetworkAdapter, "WHERE PhysicalAdapter=True and MACAddress <> null")
    71  		err := queryWmi(q, &dstNetworkAdapter)
    72  		if err != nil {
    73  			slog.Error(err)
    74  			return
    75  		}
    76  		for _, nic := range dstNetworkAdapter {
    77  			var iface = fmt.Sprint("Interface", nic.InterfaceIndex)
    78  			// Get PnPName using Win32_PnPEntity class
    79  			var pnpname = ""
    80  			var escapeddeviceid = strings.Replace(nic.PNPDeviceID, "\\", "\\\\", -1)
    81  			var filter = fmt.Sprintf("WHERE DeviceID='%s'", escapeddeviceid)
    82  			var dstPnPName []Win32_PnPEntity
    83  			q = wmi.CreateQuery(&dstPnPName, filter)
    84  			err = queryWmi(q, &dstPnPName)
    85  			if err != nil {
    86  				slog.Error(err)
    87  				return
    88  			}
    89  			for _, pnp := range dstPnPName { // Really should be a single item
    90  				pnpname = pnp.Name
    91  			}
    92  			if pnpname == "" {
    93  				slog.Errorf("%s cannot find Win32_PnPEntity %s", iface, filter)
    94  				continue
    95  			}
    96  
    97  			// Convert to instance name (see http://goo.gl/jfq6pq )
    98  			instanceName := winNetworkToInstanceName(pnpname)
    99  			mNicInstanceNameToInterfaceIndex[instanceName] = iface
   100  		}
   101  	}
   102  	update()
   103  	go func() {
   104  		for range time.Tick(time.Minute * 5) {
   105  			update()
   106  		}
   107  	}()
   108  }
   109  
   110  func c_network_windows() (opentsdb.MultiDataPoint, error) {
   111  	var dstStats []Win32_PerfRawData_Tcpip_NetworkInterface
   112  	var q = wmi.CreateQuery(&dstStats, "")
   113  	err := queryWmi(q, &dstStats)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	var md opentsdb.MultiDataPoint
   119  	for _, nicStats := range dstStats {
   120  		if interfaceExclusions.MatchString(nicStats.Name) {
   121  			continue
   122  		}
   123  
   124  		iface := mNicInstanceNameToInterfaceIndex[nicStats.Name]
   125  		if iface == "" {
   126  			continue
   127  		}
   128  		// This does NOT include TEAM network adapters. Those will go to os.net.bond
   129  		tagsIn := opentsdb.TagSet{"iface": iface, "direction": "in"}
   130  		tagsOut := opentsdb.TagSet{"iface": iface, "direction": "out"}
   131  		Add(&md, "win.net.ifspeed", nicStats.CurrentBandwidth, opentsdb.TagSet{"iface": iface}, metadata.Gauge, metadata.BitsPerSecond, descWinNetCurrentBandwidth)
   132  		Add(&md, "win.net.bytes", nicStats.BytesReceivedPersec, tagsIn, metadata.Counter, metadata.BytesPerSecond, descWinNetBytesReceivedPersec)
   133  		Add(&md, "win.net.bytes", nicStats.BytesSentPersec, tagsOut, metadata.Counter, metadata.BytesPerSecond, descWinNetBytesSentPersec)
   134  		Add(&md, "win.net.packets", nicStats.PacketsReceivedPersec, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetPacketsReceivedPersec)
   135  		Add(&md, "win.net.packets", nicStats.PacketsSentPersec, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetPacketsSentPersec)
   136  		Add(&md, "win.net.dropped", nicStats.PacketsOutboundDiscarded, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetPacketsOutboundDiscarded)
   137  		Add(&md, "win.net.dropped", nicStats.PacketsReceivedDiscarded, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetPacketsReceivedDiscarded)
   138  		Add(&md, "win.net.errs", nicStats.PacketsOutboundErrors, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetPacketsOutboundErrors)
   139  		Add(&md, "win.net.errs", nicStats.PacketsReceivedErrors, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetPacketsReceivedErrors)
   140  		Add(&md, osNetIfSpeed, nicStats.CurrentBandwidth/1000000, opentsdb.TagSet{"iface": iface}, metadata.Gauge, metadata.Megabit, osNetIfSpeedDesc)
   141  		Add(&md, osNetBytes, nicStats.BytesReceivedPersec, tagsIn, metadata.Counter, metadata.BytesPerSecond, osNetBytesDesc)
   142  		Add(&md, osNetBytes, nicStats.BytesSentPersec, tagsOut, metadata.Counter, metadata.BytesPerSecond, osNetBytesDesc)
   143  		Add(&md, osNetPackets, nicStats.PacketsReceivedPersec, tagsIn, metadata.Counter, metadata.PerSecond, osNetPacketsDesc)
   144  		Add(&md, osNetPackets, nicStats.PacketsSentPersec, tagsOut, metadata.Counter, metadata.PerSecond, osNetPacketsDesc)
   145  		Add(&md, osNetDropped, nicStats.PacketsOutboundDiscarded, tagsOut, metadata.Counter, metadata.PerSecond, osNetDroppedDesc)
   146  		Add(&md, osNetDropped, nicStats.PacketsReceivedDiscarded, tagsIn, metadata.Counter, metadata.PerSecond, osNetDroppedDesc)
   147  		Add(&md, osNetErrors, nicStats.PacketsOutboundErrors, tagsOut, metadata.Counter, metadata.PerSecond, osNetErrorsDesc)
   148  		Add(&md, osNetErrors, nicStats.PacketsReceivedErrors, tagsIn, metadata.Counter, metadata.PerSecond, osNetErrorsDesc)
   149  	}
   150  	return md, nil
   151  }
   152  
   153  const (
   154  	descWinNetCurrentBandwidth         = "Estimate of the interface's current bandwidth in bits per second (bps). For interfaces that do not vary in bandwidth or for those where no accurate estimation can be made, this value is the nominal bandwidth."
   155  	descWinNetBytesReceivedPersec      = "Bytes Received/sec is the rate at which bytes are received over each network adapter, including framing characters. Network Interface\\Bytes Received/sec is a subset of Network Interface\\Bytes Total/sec."
   156  	descWinNetBytesSentPersec          = "Bytes Sent/sec is the rate at which bytes are sent over each network adapter, including framing characters. Network Interface\\Bytes Sent/sec is a subset of Network Interface\\Bytes Total/sec."
   157  	descWinNetPacketsReceivedPersec    = "Packets Received/sec is the rate at which packets are received on the network interface."
   158  	descWinNetPacketsSentPersec        = "Packets Sent/sec is the rate at which packets are sent on the network interface."
   159  	descWinNetPacketsOutboundDiscarded = "Packets Outbound Discarded is the number of outbound packets that were chosen to be discarded even though no errors had been detected to prevent transmission. One possible reason for discarding packets could be to free up buffer space."
   160  	descWinNetPacketsReceivedDiscarded = "Packets Received Discarded is the number of inbound packets that were chosen to be discarded even though no errors had been detected to prevent their delivery to a higher-layer protocol.  One possible reason for discarding packets could be to free up buffer space."
   161  	descWinNetPacketsOutboundErrors    = "Packets Outbound Errors is the number of outbound packets that could not be transmitted because of errors."
   162  	descWinNetPacketsReceivedErrors    = "Packets Received Errors is the number of inbound packets that contained errors preventing them from being deliverable to a higher-layer protocol."
   163  )
   164  
   165  type Win32_PnPEntity struct {
   166  	Name string // Intel(R) Gigabit ET Quad Port Server Adapter #3
   167  }
   168  
   169  type Win32_NetworkAdapter struct {
   170  	Description     string // Intel(R) Gigabit ET Quad Port Server Adapter (no index)
   171  	InterfaceIndex  uint32
   172  	PNPDeviceID     string
   173  	NetConnectionID string  //NY-WEB09-PRI-NIC-A
   174  	Speed           *uint64 //Bits per Second
   175  	MACAddress      string  //00:1B:21:93:00:00
   176  	GUID            string
   177  }
   178  
   179  type Win32_PerfRawData_Tcpip_NetworkInterface struct {
   180  	CurrentBandwidth         uint64
   181  	BytesReceivedPersec      uint64
   182  	BytesSentPersec          uint64
   183  	Name                     string
   184  	PacketsOutboundDiscarded uint64
   185  	PacketsOutboundErrors    uint64
   186  	PacketsReceivedDiscarded uint64
   187  	PacketsReceivedErrors    uint64
   188  	PacketsReceivedPersec    uint64
   189  	PacketsSentPersec        uint64
   190  }
   191  
   192  // c_network_team_windows will add metrics for team network adapters from
   193  // MSFT_NetAdapterStatisticsSettingData for any adapters that are in
   194  // MSFT_NetLbfoTeamNic and have a valid instanceName.
   195  func c_network_team_windows() (opentsdb.MultiDataPoint, error) {
   196  	var dstTeamNic []*MSFT_NetLbfoTeamNic
   197  	err := queryWmiNamespace(queryTeamAdapter, &dstTeamNic, namespaceStandardCimv2)
   198  	if err != nil {
   199  		return nil, err
   200  	}
   201  
   202  	var dstStats []MSFT_NetAdapterStatisticsSettingData
   203  	err = queryWmiNamespace(queryTeamStats, &dstStats, namespaceStandardCimv2)
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	mDescriptionToTeamNic := make(map[string]*MSFT_NetLbfoTeamNic)
   209  	for _, teamNic := range dstTeamNic {
   210  		mDescriptionToTeamNic[teamNic.InterfaceDescription] = teamNic
   211  	}
   212  
   213  	var md opentsdb.MultiDataPoint
   214  	for _, nicStats := range dstStats {
   215  		TeamNic := mDescriptionToTeamNic[nicStats.InterfaceDescription]
   216  		if TeamNic == nil {
   217  			continue
   218  		}
   219  
   220  		instanceName := winNetworkToInstanceName(nicStats.InterfaceDescription)
   221  		iface := mNicInstanceNameToInterfaceIndex[instanceName]
   222  		if iface == "" {
   223  			continue
   224  		}
   225  		tagsIn := opentsdb.TagSet{"iface": iface, "direction": "in"}
   226  		tagsOut := opentsdb.TagSet{"iface": iface, "direction": "out"}
   227  		linkSpeed := math.Min(float64(TeamNic.ReceiveLinkSpeed), float64(TeamNic.Transmitlinkspeed))
   228  		Add(&md, "win.net.bond.ifspeed", linkSpeed, opentsdb.TagSet{"iface": iface}, metadata.Gauge, metadata.BitsPerSecond, descWinNetTeamlinkspeed)
   229  		Add(&md, "win.net.bond.bytes", nicStats.ReceivedBytes, tagsIn, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamReceivedBytes)
   230  		Add(&md, "win.net.bond.bytes", nicStats.SentBytes, tagsOut, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamSentBytes)
   231  		Add(&md, "win.net.bond.bytes_unicast", nicStats.ReceivedUnicastBytes, tagsIn, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamReceivedUnicastBytes)
   232  		Add(&md, "win.net.bond.bytes_unicast", nicStats.SentUnicastBytes, tagsOut, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamSentUnicastBytes)
   233  		Add(&md, "win.net.bond.bytes_broadcast", nicStats.ReceivedBroadcastBytes, tagsIn, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamReceivedBroadcastBytes)
   234  		Add(&md, "win.net.bond.bytes_broadcast", nicStats.SentBroadcastBytes, tagsOut, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamSentBroadcastBytes)
   235  		Add(&md, "win.net.bond.bytes_multicast", nicStats.ReceivedMulticastBytes, tagsIn, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamReceivedMulticastBytes)
   236  		Add(&md, "win.net.bond.bytes_multicast", nicStats.SentMulticastBytes, tagsOut, metadata.Counter, metadata.BytesPerSecond, descWinNetTeamSentMulticastBytes)
   237  		Add(&md, "win.net.bond.packets_unicast", nicStats.ReceivedUnicastPackets, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetTeamReceivedUnicastPackets)
   238  		Add(&md, "win.net.bond.packets_unicast", nicStats.SentUnicastPackets, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetTeamSentUnicastPackets)
   239  		Add(&md, "win.net.bond.dropped", nicStats.ReceivedDiscardedPackets, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetTeamReceivedDiscardedPackets)
   240  		Add(&md, "win.net.bond.dropped", nicStats.OutboundDiscardedPackets, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetTeamOutboundDiscardedPackets)
   241  		Add(&md, "win.net.bond.errs", nicStats.ReceivedPacketErrors, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetTeamReceivedPacketErrors)
   242  		Add(&md, "win.net.bond.errs", nicStats.OutboundPacketErrors, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetTeamOutboundPacketErrors)
   243  		Add(&md, "win.net.bond.packets_multicast", nicStats.ReceivedMulticastPackets, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetTeamReceivedMulticastPackets)
   244  		Add(&md, "win.net.bond.packets_multicast", nicStats.SentMulticastPackets, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetTeamSentMulticastPackets)
   245  		Add(&md, "win.net.bond.packets_broadcast", nicStats.ReceivedBroadcastPackets, tagsIn, metadata.Counter, metadata.PerSecond, descWinNetTeamReceivedBroadcastPackets)
   246  		Add(&md, "win.net.bond.packets_broadcast", nicStats.SentBroadcastPackets, tagsOut, metadata.Counter, metadata.PerSecond, descWinNetTeamSentBroadcastPackets)
   247  		Add(&md, osNetBondIfSpeed, linkSpeed/1000000, opentsdb.TagSet{"iface": iface}, metadata.Gauge, metadata.Megabit, osNetIfSpeedDesc)
   248  		Add(&md, osNetBondBytes, nicStats.ReceivedBytes, tagsIn, metadata.Counter, metadata.Bytes, osNetBytesDesc)
   249  		Add(&md, osNetBondBytes, nicStats.SentBytes, tagsOut, metadata.Counter, metadata.Bytes, osNetBytesDesc)
   250  		Add(&md, osNetBondUnicast, nicStats.ReceivedUnicastPackets, tagsIn, metadata.Counter, metadata.Count, osNetUnicastDesc)
   251  		Add(&md, osNetBondUnicast, nicStats.SentUnicastPackets, tagsOut, metadata.Counter, metadata.Count, osNetUnicastDesc)
   252  		Add(&md, osNetBondMulticast, nicStats.ReceivedMulticastPackets, tagsIn, metadata.Counter, metadata.Count, osNetMulticastDesc)
   253  		Add(&md, osNetBondMulticast, nicStats.SentMulticastPackets, tagsOut, metadata.Counter, metadata.Count, osNetMulticastDesc)
   254  		Add(&md, osNetBondBroadcast, nicStats.ReceivedBroadcastPackets, tagsIn, metadata.Counter, metadata.Count, osNetBroadcastDesc)
   255  		Add(&md, osNetBondBroadcast, nicStats.SentBroadcastPackets, tagsOut, metadata.Counter, metadata.Count, osNetBroadcastDesc)
   256  		Add(&md, osNetBondPackets, float64(nicStats.ReceivedUnicastPackets)+float64(nicStats.ReceivedMulticastPackets)+float64(nicStats.ReceivedBroadcastPackets), tagsIn, metadata.Counter, metadata.Count, osNetPacketsDesc)
   257  		Add(&md, osNetBondPackets, float64(nicStats.SentUnicastPackets)+float64(nicStats.SentMulticastPackets)+float64(nicStats.SentBroadcastPackets), tagsOut, metadata.Counter, metadata.Count, osNetPacketsDesc)
   258  		Add(&md, osNetBondDropped, nicStats.ReceivedDiscardedPackets, tagsIn, metadata.Counter, metadata.Count, osNetDroppedDesc)
   259  		Add(&md, osNetBondDropped, nicStats.OutboundDiscardedPackets, tagsOut, metadata.Counter, metadata.Count, osNetDroppedDesc)
   260  		Add(&md, osNetBondErrors, nicStats.ReceivedPacketErrors, tagsIn, metadata.Counter, metadata.Count, osNetErrorsDesc)
   261  		Add(&md, osNetBondErrors, nicStats.OutboundPacketErrors, tagsOut, metadata.Counter, metadata.Count, osNetErrorsDesc)
   262  	}
   263  	return md, nil
   264  }
   265  
   266  const (
   267  	descWinNetTeamlinkspeed                = "The link speed of the adapter in bits per second."
   268  	descWinNetTeamReceivedBytes            = "The number of bytes of data received without errors through this interface. This value includes bytes in unicast, broadcast, and multicast packets."
   269  	descWinNetTeamReceivedUnicastPackets   = "The number of unicast packets received without errors through this interface."
   270  	descWinNetTeamReceivedMulticastPackets = "The number of multicast packets received without errors through this interface."
   271  	descWinNetTeamReceivedBroadcastPackets = "The number of broadcast packets received without errors through this interface."
   272  	descWinNetTeamReceivedUnicastBytes     = "The number of unicast bytes received without errors through this interface."
   273  	descWinNetTeamReceivedMulticastBytes   = "The number of multicast bytes received without errors through this interface."
   274  	descWinNetTeamReceivedBroadcastBytes   = "The number of broadcast bytes received without errors through this interface."
   275  	descWinNetTeamReceivedDiscardedPackets = "The number of inbound packets which were chosen to be discarded even though no errors were detected to prevent the packets from being deliverable to a higher-layer protocol."
   276  	descWinNetTeamReceivedPacketErrors     = "The number of incoming packets that were discarded because of errors."
   277  	descWinNetTeamSentBytes                = "The number of bytes of data transmitted without errors through this interface. This value includes bytes in unicast, broadcast, and multicast packets."
   278  	descWinNetTeamSentUnicastPackets       = "The number of unicast packets transmitted without errors through this interface."
   279  	descWinNetTeamSentMulticastPackets     = "The number of multicast packets transmitted without errors through this interface."
   280  	descWinNetTeamSentBroadcastPackets     = "The number of broadcast packets transmitted without errors through this interface."
   281  	descWinNetTeamSentUnicastBytes         = "The number of unicast bytes transmitted without errors through this interface."
   282  	descWinNetTeamSentMulticastBytes       = "The number of multicast bytes transmitted without errors through this interface."
   283  	descWinNetTeamSentBroadcastBytes       = "The number of broadcast bytes transmitted without errors through this interface."
   284  	descWinNetTeamOutboundDiscardedPackets = "The number of outgoing packets that were discarded even though they did not have errors."
   285  	descWinNetTeamOutboundPacketErrors     = "The number of outgoing packets that were discarded because of errors."
   286  )
   287  
   288  type MSFT_NetLbfoTeamNic struct {
   289  	Team                 string
   290  	Name                 string
   291  	ReceiveLinkSpeed     uint64
   292  	Transmitlinkspeed    uint64
   293  	InterfaceDescription string
   294  }
   295  
   296  type MSFT_NetAdapterStatisticsSettingData struct {
   297  	InstanceID               string
   298  	Name                     string
   299  	InterfaceDescription     string
   300  	ReceivedBytes            uint64
   301  	ReceivedUnicastPackets   uint64
   302  	ReceivedMulticastPackets uint64
   303  	ReceivedBroadcastPackets uint64
   304  	ReceivedUnicastBytes     uint64
   305  	ReceivedMulticastBytes   uint64
   306  	ReceivedBroadcastBytes   uint64
   307  	ReceivedDiscardedPackets uint64
   308  	ReceivedPacketErrors     uint64
   309  	SentBytes                uint64
   310  	SentUnicastPackets       uint64
   311  	SentMulticastPackets     uint64
   312  	SentBroadcastPackets     uint64
   313  	SentUnicastBytes         uint64
   314  	SentMulticastBytes       uint64
   315  	SentBroadcastBytes       uint64
   316  	OutboundDiscardedPackets uint64
   317  	OutboundPacketErrors     uint64
   318  }
   319  
   320  var (
   321  	winNetTCPSegmentsLastCount           uint32
   322  	winNetTCPSegmentsLastRetransmitCount uint32
   323  )
   324  
   325  func c_network_windows_tcp() (opentsdb.MultiDataPoint, error) {
   326  	var dst []Win32_PerfRawData_Tcpip_TCPv4
   327  	err := queryWmi(winNetTCPQuery, &dst)
   328  	if err != nil {
   329  		return nil, err
   330  	}
   331  	var md opentsdb.MultiDataPoint
   332  	for _, v := range dst {
   333  		Add(&md, "win.net.tcp.failures", v.ConnectionFailures, nil, metadata.Counter, metadata.Connection, descWinNetTCPv4ConnectionFailures)
   334  		Add(&md, "win.net.tcp.active", v.ConnectionsActive, nil, metadata.Counter, metadata.Connection, descWinNetTCPv4ConnectionsActive)
   335  		Add(&md, "win.net.tcp.established", v.ConnectionsEstablished, nil, metadata.Gauge, metadata.Connection, descWinNetTCPv4ConnectionsEstablished)
   336  		Add(&md, "win.net.tcp.passive", v.ConnectionsPassive, nil, metadata.Counter, metadata.Connection, descWinNetTCPv4ConnectionsPassive)
   337  		Add(&md, "win.net.tcp.reset", v.ConnectionsReset, nil, metadata.Gauge, metadata.Connection, descWinNetTCPv4ConnectionsReset)
   338  		Add(&md, "win.net.tcp.segments", v.SegmentsReceivedPersec, opentsdb.TagSet{"type": "received"}, metadata.Counter, metadata.PerSecond, descWinNetTCPv4SegmentsReceivedPersec)
   339  		Add(&md, "win.net.tcp.segments", v.SegmentsRetransmittedPersec, opentsdb.TagSet{"type": "retransmitted"}, metadata.Counter, metadata.PerSecond, descWinNetTCPv4SegmentsRetransmittedPersec)
   340  		Add(&md, "win.net.tcp.segments", v.SegmentsSentPersec, opentsdb.TagSet{"type": "sent"}, metadata.Counter, metadata.PerSecond, descWinNetTCPv4SegmentsSentPersec)
   341  		if winNetTCPSegmentsLastCount != 0 &&
   342  			(v.SegmentsPersec-winNetTCPSegmentsLastCount) != 0 &&
   343  			(v.SegmentsRetransmittedPersec > winNetTCPSegmentsLastRetransmitCount) &&
   344  			(v.SegmentsPersec > winNetTCPSegmentsLastCount) {
   345  			val := float64(v.SegmentsRetransmittedPersec-winNetTCPSegmentsLastRetransmitCount) / float64(v.SegmentsPersec-winNetTCPSegmentsLastCount) * 100
   346  			Add(&md, "win.net.tcp.retransmit_pct", val, nil, metadata.Gauge, metadata.Pct, descWinNetTCPv4SegmentsRetransmit)
   347  		}
   348  		winNetTCPSegmentsLastRetransmitCount = v.SegmentsRetransmittedPersec
   349  		winNetTCPSegmentsLastCount = v.SegmentsPersec
   350  	}
   351  	return md, nil
   352  }
   353  
   354  const (
   355  	descWinNetTCPv4ConnectionFailures          = "Connection Failures is the number of times TCP connections have made a direct transition to the CLOSED state from the SYN-SENT state or the SYN-RCVD state, plus the number of times TCP connections have made a direct transition to the LISTEN state from the SYN-RCVD state."
   356  	descWinNetTCPv4ConnectionsActive           = "Connections Active is the number of times TCP connections have made a direct transition to the SYN-SENT state from the CLOSED state. In other words, it shows a number of connections which are initiated by the local computer. The value is a cumulative total."
   357  	descWinNetTCPv4ConnectionsEstablished      = "Connections Established is the number of TCP connections for which the current state is either ESTABLISHED or CLOSE-WAIT."
   358  	descWinNetTCPv4ConnectionsPassive          = "Connections Passive is the number of times TCP connections have made a direct transition to the SYN-RCVD state from the LISTEN state. In other words, it shows a number of connections to the local computer, which are initiated by remote computers. The value is a cumulative total."
   359  	descWinNetTCPv4ConnectionsReset            = "Connections Reset is the number of times TCP connections have made a direct transition to the CLOSED state from either the ESTABLISHED state or the CLOSE-WAIT state."
   360  	descWinNetTCPv4SegmentsReceivedPersec      = "Segments Received/sec is the rate at which segments are received, including those received in error.  This count includes segments received on currently established connections."
   361  	descWinNetTCPv4SegmentsRetransmittedPersec = "Segments Retransmitted/sec is the rate at which segments are retransmitted, that is, segments transmitted containing one or more previously transmitted bytes."
   362  	descWinNetTCPv4SegmentsSentPersec          = "Segments Sent/sec is the rate at which segments are sent, including those on current connections, but excluding those containing only retransmitted bytes."
   363  	descWinNetTCPv4SegmentsRetransmit          = "Segments Retransmitted / (Segments Sent + Segments Received). Usually expected to be less than 0.1 - 0.01 percent, and anything above 1 percent is an indicator of a poor connection."
   364  )
   365  
   366  type Win32_PerfRawData_Tcpip_TCPv4 struct {
   367  	ConnectionFailures          uint32
   368  	ConnectionsActive           uint32
   369  	ConnectionsEstablished      uint32
   370  	ConnectionsPassive          uint32
   371  	ConnectionsReset            uint32
   372  	SegmentsPersec              uint32
   373  	SegmentsReceivedPersec      uint32
   374  	SegmentsRetransmittedPersec uint32
   375  	SegmentsSentPersec          uint32
   376  }