net.go (8330B)
1 // Copyright The OpenTelemetry Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package internal // import "go.opentelemetry.io/otel/semconv/internal/v2" 16 17 import ( 18 "net" 19 "strconv" 20 "strings" 21 22 "go.opentelemetry.io/otel/attribute" 23 ) 24 25 // NetConv are the network semantic convention attributes defined for a version 26 // of the OpenTelemetry specification. 27 type NetConv struct { 28 NetHostNameKey attribute.Key 29 NetHostPortKey attribute.Key 30 NetPeerNameKey attribute.Key 31 NetPeerPortKey attribute.Key 32 NetSockFamilyKey attribute.Key 33 NetSockPeerAddrKey attribute.Key 34 NetSockPeerPortKey attribute.Key 35 NetSockHostAddrKey attribute.Key 36 NetSockHostPortKey attribute.Key 37 NetTransportOther attribute.KeyValue 38 NetTransportTCP attribute.KeyValue 39 NetTransportUDP attribute.KeyValue 40 NetTransportInProc attribute.KeyValue 41 } 42 43 func (c *NetConv) Transport(network string) attribute.KeyValue { 44 switch network { 45 case "tcp", "tcp4", "tcp6": 46 return c.NetTransportTCP 47 case "udp", "udp4", "udp6": 48 return c.NetTransportUDP 49 case "unix", "unixgram", "unixpacket": 50 return c.NetTransportInProc 51 default: 52 // "ip:*", "ip4:*", and "ip6:*" all are considered other. 53 return c.NetTransportOther 54 } 55 } 56 57 // Host returns attributes for a network host address. 58 func (c *NetConv) Host(address string) []attribute.KeyValue { 59 h, p := splitHostPort(address) 60 var n int 61 if h != "" { 62 n++ 63 if p > 0 { 64 n++ 65 } 66 } 67 68 if n == 0 { 69 return nil 70 } 71 72 attrs := make([]attribute.KeyValue, 0, n) 73 attrs = append(attrs, c.HostName(h)) 74 if p > 0 { 75 attrs = append(attrs, c.HostPort(int(p))) 76 } 77 return attrs 78 } 79 80 // Server returns attributes for a network listener listening at address. See 81 // net.Listen for information about acceptable address values, address should 82 // be the same as the one used to create ln. If ln is nil, only network host 83 // attributes will be returned that describe address. Otherwise, the socket 84 // level information about ln will also be included. 85 func (c *NetConv) Server(address string, ln net.Listener) []attribute.KeyValue { 86 if ln == nil { 87 return c.Host(address) 88 } 89 90 lAddr := ln.Addr() 91 if lAddr == nil { 92 return c.Host(address) 93 } 94 95 hostName, hostPort := splitHostPort(address) 96 sockHostAddr, sockHostPort := splitHostPort(lAddr.String()) 97 network := lAddr.Network() 98 sockFamily := family(network, sockHostAddr) 99 100 n := nonZeroStr(hostName, network, sockHostAddr, sockFamily) 101 n += positiveInt(hostPort, sockHostPort) 102 attr := make([]attribute.KeyValue, 0, n) 103 if hostName != "" { 104 attr = append(attr, c.HostName(hostName)) 105 if hostPort > 0 { 106 // Only if net.host.name is set should net.host.port be. 107 attr = append(attr, c.HostPort(hostPort)) 108 } 109 } 110 if network != "" { 111 attr = append(attr, c.Transport(network)) 112 } 113 if sockFamily != "" { 114 attr = append(attr, c.NetSockFamilyKey.String(sockFamily)) 115 } 116 if sockHostAddr != "" { 117 attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr)) 118 if sockHostPort > 0 { 119 // Only if net.sock.host.addr is set should net.sock.host.port be. 120 attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort)) 121 } 122 } 123 return attr 124 } 125 126 func (c *NetConv) HostName(name string) attribute.KeyValue { 127 return c.NetHostNameKey.String(name) 128 } 129 130 func (c *NetConv) HostPort(port int) attribute.KeyValue { 131 return c.NetHostPortKey.Int(port) 132 } 133 134 // Client returns attributes for a client network connection to address. See 135 // net.Dial for information about acceptable address values, address should be 136 // the same as the one used to create conn. If conn is nil, only network peer 137 // attributes will be returned that describe address. Otherwise, the socket 138 // level information about conn will also be included. 139 func (c *NetConv) Client(address string, conn net.Conn) []attribute.KeyValue { 140 if conn == nil { 141 return c.Peer(address) 142 } 143 144 lAddr, rAddr := conn.LocalAddr(), conn.RemoteAddr() 145 146 var network string 147 switch { 148 case lAddr != nil: 149 network = lAddr.Network() 150 case rAddr != nil: 151 network = rAddr.Network() 152 default: 153 return c.Peer(address) 154 } 155 156 peerName, peerPort := splitHostPort(address) 157 var ( 158 sockFamily string 159 sockPeerAddr string 160 sockPeerPort int 161 sockHostAddr string 162 sockHostPort int 163 ) 164 165 if lAddr != nil { 166 sockHostAddr, sockHostPort = splitHostPort(lAddr.String()) 167 } 168 169 if rAddr != nil { 170 sockPeerAddr, sockPeerPort = splitHostPort(rAddr.String()) 171 } 172 173 switch { 174 case sockHostAddr != "": 175 sockFamily = family(network, sockHostAddr) 176 case sockPeerAddr != "": 177 sockFamily = family(network, sockPeerAddr) 178 } 179 180 n := nonZeroStr(peerName, network, sockPeerAddr, sockHostAddr, sockFamily) 181 n += positiveInt(peerPort, sockPeerPort, sockHostPort) 182 attr := make([]attribute.KeyValue, 0, n) 183 if peerName != "" { 184 attr = append(attr, c.PeerName(peerName)) 185 if peerPort > 0 { 186 // Only if net.peer.name is set should net.peer.port be. 187 attr = append(attr, c.PeerPort(peerPort)) 188 } 189 } 190 if network != "" { 191 attr = append(attr, c.Transport(network)) 192 } 193 if sockFamily != "" { 194 attr = append(attr, c.NetSockFamilyKey.String(sockFamily)) 195 } 196 if sockPeerAddr != "" { 197 attr = append(attr, c.NetSockPeerAddrKey.String(sockPeerAddr)) 198 if sockPeerPort > 0 { 199 // Only if net.sock.peer.addr is set should net.sock.peer.port be. 200 attr = append(attr, c.NetSockPeerPortKey.Int(sockPeerPort)) 201 } 202 } 203 if sockHostAddr != "" { 204 attr = append(attr, c.NetSockHostAddrKey.String(sockHostAddr)) 205 if sockHostPort > 0 { 206 // Only if net.sock.host.addr is set should net.sock.host.port be. 207 attr = append(attr, c.NetSockHostPortKey.Int(sockHostPort)) 208 } 209 } 210 return attr 211 } 212 213 func family(network, address string) string { 214 switch network { 215 case "unix", "unixgram", "unixpacket": 216 return "unix" 217 default: 218 if ip := net.ParseIP(address); ip != nil { 219 if ip.To4() == nil { 220 return "inet6" 221 } 222 return "inet" 223 } 224 } 225 return "" 226 } 227 228 func nonZeroStr(strs ...string) int { 229 var n int 230 for _, str := range strs { 231 if str != "" { 232 n++ 233 } 234 } 235 return n 236 } 237 238 func positiveInt(ints ...int) int { 239 var n int 240 for _, i := range ints { 241 if i > 0 { 242 n++ 243 } 244 } 245 return n 246 } 247 248 // Peer returns attributes for a network peer address. 249 func (c *NetConv) Peer(address string) []attribute.KeyValue { 250 h, p := splitHostPort(address) 251 var n int 252 if h != "" { 253 n++ 254 if p > 0 { 255 n++ 256 } 257 } 258 259 if n == 0 { 260 return nil 261 } 262 263 attrs := make([]attribute.KeyValue, 0, n) 264 attrs = append(attrs, c.PeerName(h)) 265 if p > 0 { 266 attrs = append(attrs, c.PeerPort(int(p))) 267 } 268 return attrs 269 } 270 271 func (c *NetConv) PeerName(name string) attribute.KeyValue { 272 return c.NetPeerNameKey.String(name) 273 } 274 275 func (c *NetConv) PeerPort(port int) attribute.KeyValue { 276 return c.NetPeerPortKey.Int(port) 277 } 278 279 func (c *NetConv) SockPeerAddr(addr string) attribute.KeyValue { 280 return c.NetSockPeerAddrKey.String(addr) 281 } 282 283 func (c *NetConv) SockPeerPort(port int) attribute.KeyValue { 284 return c.NetSockPeerPortKey.Int(port) 285 } 286 287 // splitHostPort splits a network address hostport of the form "host", 288 // "host%zone", "[host]", "[host%zone], "host:port", "host%zone:port", 289 // "[host]:port", "[host%zone]:port", or ":port" into host or host%zone and 290 // port. 291 // 292 // An empty host is returned if it is not provided or unparsable. A negative 293 // port is returned if it is not provided or unparsable. 294 func splitHostPort(hostport string) (host string, port int) { 295 port = -1 296 297 if strings.HasPrefix(hostport, "[") { 298 addrEnd := strings.LastIndex(hostport, "]") 299 if addrEnd < 0 { 300 // Invalid hostport. 301 return 302 } 303 if i := strings.LastIndex(hostport[addrEnd:], ":"); i < 0 { 304 host = hostport[1:addrEnd] 305 return 306 } 307 } else { 308 if i := strings.LastIndex(hostport, ":"); i < 0 { 309 host = hostport 310 return 311 } 312 } 313 314 host, pStr, err := net.SplitHostPort(hostport) 315 if err != nil { 316 return 317 } 318 319 p, err := strconv.ParseUint(pStr, 10, 16) 320 if err != nil { 321 return 322 } 323 return host, int(p) 324 }