github.com/newrelic/go-agent@v3.26.0+incompatible/internal/utilization/addresses.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package utilization 5 6 import ( 7 "fmt" 8 "net" 9 ) 10 11 func nonlocalIPAddressesByInterface() (map[string][]string, error) { 12 ifaces, err := net.Interfaces() 13 if err != nil { 14 return nil, err 15 } 16 ips := make(map[string][]string, len(ifaces)) 17 for _, ifc := range ifaces { 18 addrs, err := ifc.Addrs() 19 if err != nil { 20 continue 21 } 22 for _, addr := range addrs { 23 var ip net.IP 24 switch iptype := addr.(type) { 25 case *net.IPAddr: 26 ip = iptype.IP 27 case *net.IPNet: 28 ip = iptype.IP 29 case *net.TCPAddr: 30 ip = iptype.IP 31 case *net.UDPAddr: 32 ip = iptype.IP 33 } 34 if nil != ip && !ip.IsLoopback() && !ip.IsUnspecified() { 35 ips[ifc.Name] = append(ips[ifc.Name], ip.String()) 36 } 37 } 38 } 39 return ips, nil 40 } 41 42 // utilizationIPs gathers IP address which may help identify this entity. This 43 // code chooses all IPs from the interface which contains the IP of a UDP 44 // connection with NR. This approach has the following advantages: 45 // * Matches the behavior of the Java agent. 46 // * Reports fewer IPs to lower linking burden on infrastructure backend. 47 // * The UDP connection interface is more likely to contain unique external IPs. 48 func utilizationIPs() ([]string, error) { 49 // Port choice designed to match 50 // https://source.datanerd.us/java-agent/java_agent/blob/master/newrelic-agent/src/main/java/com/newrelic/agent/config/Hostname.java#L110 51 conn, err := net.Dial("udp", "newrelic.com:10002") 52 if err != nil { 53 return nil, err 54 } 55 defer conn.Close() 56 57 addr, ok := conn.LocalAddr().(*net.UDPAddr) 58 59 if !ok || nil == addr || addr.IP.IsLoopback() || addr.IP.IsUnspecified() { 60 return nil, fmt.Errorf("unexpected connection address: %v", conn.LocalAddr()) 61 } 62 outboundIP := addr.IP.String() 63 64 ipsByInterface, err := nonlocalIPAddressesByInterface() 65 if err != nil { 66 return nil, err 67 } 68 for _, ips := range ipsByInterface { 69 for _, ip := range ips { 70 if ip == outboundIP { 71 return ips, nil 72 } 73 } 74 } 75 return nil, nil 76 }