ClassifyDialErrorSubCode provides more granular classification of dial errors to help identify root causes (DNS, VPN, timeouts, etc.)
(err error)
| 173 | // ClassifyDialErrorSubCode provides more granular classification of dial errors |
| 174 | // to help identify root causes (DNS, VPN, timeouts, etc.) |
| 175 | func ClassifyDialErrorSubCode(err error) string { |
| 176 | if err == nil { |
| 177 | return "" |
| 178 | } |
| 179 | |
| 180 | // Check for context cancellation first |
| 181 | if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { |
| 182 | return DialSubCode_ContextCanceled |
| 183 | } |
| 184 | |
| 185 | // Check if it's a DNS error |
| 186 | var dnsErr *net.DNSError |
| 187 | if errors.As(err, &dnsErr) { |
| 188 | return DialSubCode_DNS |
| 189 | } |
| 190 | |
| 191 | // Check if it's a network operation error |
| 192 | var opErr *net.OpError |
| 193 | if errors.As(err, &opErr) { |
| 194 | // Check the underlying error for more details |
| 195 | if opErr.Err != nil { |
| 196 | errStr := opErr.Err.Error() |
| 197 | if strings.Contains(errStr, "connection refused") { |
| 198 | return DialSubCode_Refused |
| 199 | } |
| 200 | if strings.Contains(errStr, "no route to host") { |
| 201 | return DialSubCode_NoRoute |
| 202 | } |
| 203 | if strings.Contains(errStr, "host is unreachable") || strings.Contains(errStr, "host unreachable") { |
| 204 | return DialSubCode_HostUnreach |
| 205 | } |
| 206 | if strings.Contains(errStr, "network is unreachable") || strings.Contains(errStr, "network unreachable") { |
| 207 | return DialSubCode_NetUnreach |
| 208 | } |
| 209 | if strings.Contains(errStr, "connection reset") { |
| 210 | return DialSubCode_ConnReset |
| 211 | } |
| 212 | if strings.Contains(errStr, "permission denied") { |
| 213 | return DialSubCode_PermDenied |
| 214 | } |
| 215 | } |
| 216 | // Generic timeout detection in OpError |
| 217 | if opErr.Timeout() { |
| 218 | return DialSubCode_Timeout |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | // Check error string for common patterns |
| 223 | errStr := err.Error() |
| 224 | if strings.Contains(errStr, "connection refused") { |
| 225 | return DialSubCode_Refused |
| 226 | } |
| 227 | if strings.Contains(errStr, "timed out") || strings.Contains(errStr, "timeout") || strings.Contains(errStr, "i/o timeout") { |
| 228 | return DialSubCode_Timeout |
| 229 | } |
| 230 | if strings.Contains(errStr, "no route to host") { |
| 231 | return DialSubCode_NoRoute |
| 232 | } |
no test coverage detected