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  }