github.com/qiniu/go-sdk/v7@v7.27.0/internal/uplog/quality_uplog.go (about)

     1  package uplog
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"runtime"
     7  	"sync/atomic"
     8  	"time"
     9  
    10  	"github.com/qiniu/go-sdk/v7/client"
    11  	"github.com/qiniu/go-sdk/v7/conf"
    12  )
    13  
    14  type qualityUplog struct {
    15  	LogType           LogType   `json:"log_type,omitempty"`
    16  	Result            LogResult `json:"result,omitempty"`
    17  	UpType            UpType    `json:"up_type,omitempty"`
    18  	TotalElapsedTime  uint64    `json:"total_elapsed_time,omitempty"`
    19  	RequestsCount     uint64    `json:"requests_count,omitempty"`
    20  	RegionsCount      uint64    `json:"regions_count,omitempty"`
    21  	BytesSent         uint64    `json:"bytes_sent,omitempty"`
    22  	BytesReceived     uint64    `json:"bytes_received,omitempty"`
    23  	FileSize          uint64    `json:"file_size,omitempty"`
    24  	APIType           APIType   `json:"api_type,omitempty"`
    25  	UpTime            int64     `json:"up_time,omitempty"`
    26  	TargetBucket      string    `json:"target_bucket,omitempty"`
    27  	TargetKey         string    `json:"target_key,omitempty"`
    28  	OSName            string    `json:"os_name,omitempty"`
    29  	OSVersion         string    `json:"os_version,omitempty"`
    30  	OSArch            string    `json:"os_arch,omitempty"`
    31  	SDKName           string    `json:"sdk_name,omitempty"`
    32  	SDKVersion        string    `json:"sdk_version,omitempty"`
    33  	HTTPClient        string    `json:"http_client,omitempty"`
    34  	HTTPClientVersion string    `json:"http_client_version,omitempty"`
    35  	ErrorType         ErrorType `json:"error_type,omitempty"`
    36  	ErrorDescription  string    `json:"error_description,omitempty"`
    37  	PerceptiveSpeed   uint64    `json:"perceptive_speed,omitempty"`
    38  }
    39  
    40  func WithQuality(ctx context.Context, upType UpType, fileSize uint64, targetBucket, targetKey, upToken string, handle func(ctx context.Context, switchRegion func()) error) error {
    41  	if !IsUplogEnabled() {
    42  		return handle(ctx, func() {})
    43  	}
    44  	uplog := qualityUplog{
    45  		LogType:           LogTypeQuality,
    46  		UpType:            upType,
    47  		FileSize:          fileSize,
    48  		TargetBucket:      truncate(targetBucket, maxFieldValueLength),
    49  		TargetKey:         truncate(targetKey, maxFieldValueLength),
    50  		APIType:           APITypeKodo,
    51  		OSName:            truncate(runtime.GOOS, maxFieldValueLength),
    52  		OSVersion:         truncate(getOsVersion(), maxFieldValueLength),
    53  		OSArch:            truncate(runtime.GOARCH, maxFieldValueLength),
    54  		SDKName:           "go",
    55  		SDKVersion:        truncate(conf.Version, maxFieldValueLength),
    56  		HTTPClient:        truncate(getHttpClientName(), maxFieldValueLength),
    57  		HTTPClientVersion: truncate(conf.Version, maxFieldValueLength),
    58  	}
    59  	bytesSentTotal, ctx := withBytesSentTotalContext(ctx, false)
    60  	bytesReceivedTotal, ctx := withBytesReceivedTotalContext(ctx, false)
    61  	requestsCount, ctx := withRequestsCountContext(ctx, false)
    62  	beginAt := time.Now()
    63  	err := handle(ctx, func() {
    64  		atomic.AddUint64(&uplog.RegionsCount, 1)
    65  	})
    66  	uplog.TotalElapsedTime = getElapsedTime(beginAt)
    67  	if err != nil {
    68  		uplog.ErrorType = detectErrorType(err)
    69  		uplog.ErrorDescription = truncate(err.Error(), maxFieldValueLength)
    70  	}
    71  	uplog.Result = detectLogResult(err)
    72  	uplog.BytesSent = atomic.LoadUint64(bytesSentTotal)
    73  	uplog.BytesReceived = atomic.LoadUint64(bytesReceivedTotal)
    74  	uplog.RequestsCount = atomic.LoadUint64(requestsCount)
    75  	if uplog.TotalElapsedTime > 0 {
    76  		if uplog.BytesSent > uplog.BytesReceived {
    77  			uplog.PerceptiveSpeed = uplog.BytesSent * 1000 / uplog.TotalElapsedTime
    78  		} else {
    79  			uplog.PerceptiveSpeed = uplog.BytesReceived * 1000 / uplog.TotalElapsedTime
    80  		}
    81  	}
    82  	if uplogBytes, jsonError := json.Marshal(uplog); jsonError == nil {
    83  		uplogChan <- uplogSerializedEntry{serializedUplog: uplogBytes, getUpToken: func() (string, error) {
    84  			return upToken, nil
    85  		}}
    86  	}
    87  	return err
    88  }
    89  
    90  func detectLogResult(err error) LogResult {
    91  	if err != nil {
    92  		if clientErr, ok := err.(*client.ErrorInfo); ok {
    93  			if clientErr.Code/100 == 4 || clientErr.Code == 573 || clientErr.Code == 579 || clientErr.Code == 608 || clientErr.Code == 612 ||
    94  				clientErr.Code == 614 || clientErr.Code == 630 || clientErr.Code == 631 || clientErr.Code == 701 {
    95  				return LogResultBadRequest
    96  			} else if clientErr.Code/100 != 2 {
    97  				return LogResultResponseError
    98  			}
    99  		}
   100  		switch detectErrorType(err) {
   101  		case ErrorTypeTimeout:
   102  			return LogResultTimeout
   103  		case ErrorTypeUnknownHost:
   104  			return LogResultUnknownHost
   105  		case ErrorTypeMaliciousResponse:
   106  			return LogResultMaliciousResponse
   107  		case ErrorTypeCannotConnectToHost:
   108  			return LogResultCannotConnectToHost
   109  		case ErrorTypeUserCanceled:
   110  			return LogResultUserCanceled
   111  		case ErrorTypeProtocolError:
   112  			return LogResultProtocolError
   113  		case ErrorTypeSSLError:
   114  			return LogResultSSLError
   115  		case ErrorTypeTransmissionError:
   116  			return LogResultTransmissionError
   117  		case ErrorTypeLocalIoError:
   118  			return LogResultLocalIoError
   119  		case ErrorTypeUnexpectedSyscallError:
   120  			return LogResultUnexpectedSyscallError
   121  		default:
   122  			return LogResultUnknownError
   123  		}
   124  	}
   125  	return LogResultOK
   126  }