github.com/qiniu/go-sdk/v7@v7.27.0/internal/uplog/uplog.go (about) 1 package uplog 2 3 import ( 4 "context" 5 "net" 6 "net/url" 7 "os" 8 "strings" 9 "syscall" 10 11 "github.com/qiniu/go-sdk/v7/storagev2/retrier" 12 ) 13 14 type ( 15 LogType string 16 APIType string 17 ErrorType string 18 UpApiVersion uint8 19 UpType string 20 LogResult string 21 ) 22 23 const ( 24 LogTypeRequest LogType = "request" 25 LogTypeBlock LogType = "block" 26 LogTypeQuality LogType = "quality" 27 LogTypeTransaction LogType = "transaction" 28 APITypeKodo APIType = "kodo" 29 ErrorTypeUnknownError ErrorType = "unknown_error" 30 ErrorTypeTimeout ErrorType = "timeout" 31 ErrorTypeUnknownHost ErrorType = "unknown_host" 32 ErrorTypeMaliciousResponse ErrorType = "malicious_response" 33 ErrorTypeCannotConnectToHost ErrorType = "cannot_connect_to_host" 34 ErrorTypeSSLError ErrorType = "ssl_error" 35 ErrorTypeTransmissionError ErrorType = "transmission_error" 36 ErrorTypeProtocolError ErrorType = "protocol_error" 37 ErrorTypeResponseError ErrorType = "response_error" 38 ErrorTypeUserCanceled ErrorType = "user_canceled" 39 ErrorTypeLocalIoError ErrorType = "local_io_error" 40 ErrorTypeUnexpectedSyscallError ErrorType = "unexpected_syscall_error" 41 UpApiVersionV1 UpApiVersion = 1 42 UpApiVersionV2 UpApiVersion = 2 43 UpTypeForm UpType = "form" 44 UpTypeResumableV1 UpType = "resumable_v1" 45 UpTypeResumableV2 UpType = "resumable_v2" 46 LogResultOK LogResult = "ok" 47 LogResultBadRequest LogResult = "bad_request" 48 LogResultInvalidArgs LogResult = "invalid_args" 49 LogResultUnknownError LogResult = "unknown_error" 50 LogResultTimeout LogResult = "timeout" 51 LogResultUnknownHost LogResult = "unknown_host" 52 LogResultMaliciousResponse LogResult = "malicious_response" 53 LogResultCannotConnectToHost LogResult = "cannot_connect_to_host" 54 LogResultSSLError LogResult = "ssl_error" 55 LogResultTransmissionError LogResult = "transmission_error" 56 LogResultProtocolError LogResult = "protocol_error" 57 LogResultResponseError LogResult = "response_error" 58 LogResultUserCanceled LogResult = "user_canceled" 59 LogResultLocalIoError LogResult = "local_io_error" 60 LogResultUnexpectedSyscallError LogResult = "unexpected_syscall_error" 61 ) 62 63 var osVersion string 64 65 func getOsVersion() string { 66 return osVersion 67 } 68 69 func detectErrorType(err error) ErrorType { 70 tryToUnwrapUnderlyingError := func(err error) (error, bool) { 71 switch err := err.(type) { 72 case *os.PathError: 73 return err.Err, true 74 case *os.LinkError: 75 return err.Err, true 76 case *os.SyscallError: 77 return err.Err, true 78 case *url.Error: 79 return err.Err, true 80 case *net.OpError: 81 return err.Err, true 82 } 83 return err, false 84 } 85 unwrapUnderlyingError := func(err error) error { 86 ok := true 87 for ok { 88 err, ok = tryToUnwrapUnderlyingError(err) 89 } 90 return err 91 } 92 93 unwrapedErr := unwrapUnderlyingError(err) 94 if unwrapedErr == retrier.ErrMaliciousResponse { 95 return ErrorTypeMaliciousResponse 96 } else if os.IsTimeout(unwrapedErr) { 97 return ErrorTypeTimeout 98 } else if dnsError, ok := unwrapedErr.(*net.DNSError); ok && isDnsNotFoundError(dnsError) { 99 return ErrorTypeUnknownHost 100 } else if os.IsNotExist(unwrapedErr) || os.IsPermission(unwrapedErr) { 101 return ErrorTypeLocalIoError 102 } else if syscallError, ok := unwrapedErr.(*os.SyscallError); ok { 103 switch syscallError.Err { 104 case syscall.ECONNREFUSED, syscall.ECONNABORTED, syscall.ECONNRESET: 105 return ErrorTypeCannotConnectToHost 106 default: 107 return ErrorTypeUnexpectedSyscallError 108 } 109 } else if errno, ok := unwrapedErr.(syscall.Errno); ok { 110 switch errno { 111 case syscall.ECONNREFUSED, syscall.ECONNABORTED, syscall.ECONNRESET: 112 return ErrorTypeCannotConnectToHost 113 default: 114 return ErrorTypeUnexpectedSyscallError 115 } 116 } else if unwrapedErr == context.Canceled { 117 return ErrorTypeUserCanceled 118 } else { 119 desc := unwrapedErr.Error() 120 if strings.HasPrefix(desc, "tls: ") || 121 strings.HasPrefix(desc, "x509: ") { 122 return ErrorTypeSSLError 123 } else if strings.Contains(desc, "use of closed network connection") || 124 strings.Contains(desc, "unexpected EOF reading trailer") || 125 strings.Contains(desc, "transport connection broken") || 126 strings.Contains(desc, "server closed idle connection") { 127 return ErrorTypeTransmissionError 128 } 129 return ErrorTypeUnknownError 130 } 131 } 132 133 func getHttpClientName() string { 134 httpClientName := "QiniuGo" 135 if testRuntime { 136 httpClientName = "QiniuGo_Debug" 137 } 138 return httpClientName 139 } 140 141 type ( 142 bytesSentContextKey struct { 143 blockLevel bool 144 } 145 bytesSentTotal struct { 146 N uint64 147 } 148 ) 149 150 func withBytesSentTotalContext(ctx context.Context, blockLevel bool) (*uint64, context.Context) { 151 brt := new(bytesSentTotal) 152 return &brt.N, context.WithValue(ctx, bytesSentContextKey{blockLevel}, brt) 153 } 154 155 func getBytesSentTotalFromContext(ctx context.Context, blockLevel bool) *uint64 { 156 if bytesSentTotal, ok := ctx.Value(bytesSentContextKey{blockLevel}).(*bytesSentTotal); ok { 157 return &bytesSentTotal.N 158 } 159 return nil 160 } 161 162 type ( 163 bytesReceivedContextKey struct { 164 blockLevel bool 165 } 166 bytesReceivedTotal struct { 167 N uint64 168 } 169 ) 170 171 func withBytesReceivedTotalContext(ctx context.Context, blockLevel bool) (*uint64, context.Context) { 172 brt := new(bytesReceivedTotal) 173 return &brt.N, context.WithValue(ctx, bytesReceivedContextKey{blockLevel}, brt) 174 } 175 176 func getBytesReceivedTotalFromContext(ctx context.Context, blockLevel bool) *uint64 { 177 if bytesReceivedTotal, ok := ctx.Value(bytesReceivedContextKey{blockLevel}).(*bytesReceivedTotal); ok { 178 return &bytesReceivedTotal.N 179 } 180 return nil 181 } 182 183 type ( 184 requestsCountContextKey struct { 185 blockLevel bool 186 } 187 requestsCount struct { 188 N uint64 189 } 190 ) 191 192 func withRequestsCountContext(ctx context.Context, blockLevel bool) (*uint64, context.Context) { 193 brt := new(requestsCount) 194 return &brt.N, context.WithValue(ctx, requestsCountContextKey{blockLevel}, brt) 195 } 196 197 func getRequestsCountFromContext(ctx context.Context, blockLevel bool) *uint64 { 198 if requestsCount, ok := ctx.Value(requestsCountContextKey{blockLevel}).(*requestsCount); ok { 199 return &requestsCount.N 200 } 201 return nil 202 }