mirror of https://github.com/tikv/client-go.git
				
				
				
			
		
			
				
	
	
		
			188 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2023 TiKV Authors
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
package util
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// RequestSourceTypeKeyType is a dummy type to avoid naming collision in context.
 | 
						|
type RequestSourceTypeKeyType struct{}
 | 
						|
 | 
						|
// RequestSourceTypeKey is used as the key of request source type in context.
 | 
						|
var RequestSourceTypeKey = RequestSourceTypeKeyType{}
 | 
						|
 | 
						|
// RequestSourceKeyType is a dummy type to avoid naming collision in context.
 | 
						|
type RequestSourceKeyType struct{}
 | 
						|
 | 
						|
// RequestSourceKey is used as the key of request source type in context.
 | 
						|
var RequestSourceKey = RequestSourceKeyType{}
 | 
						|
 | 
						|
const (
 | 
						|
	// InternalTxnOthers is the type of requests that consume low resources.
 | 
						|
	// This reduces the size of metrics.
 | 
						|
	InternalTxnOthers = "others"
 | 
						|
	// InternalTxnGC is the type of GC txn.
 | 
						|
	InternalTxnGC = "gc"
 | 
						|
	// InternalTxnMeta is the type of the miscellaneous meta usage.
 | 
						|
	InternalTxnMeta = InternalTxnOthers
 | 
						|
)
 | 
						|
 | 
						|
// explicit source types.
 | 
						|
const (
 | 
						|
	ExplicitTypeEmpty      = ""
 | 
						|
	ExplicitTypeLightning  = "lightning"
 | 
						|
	ExplicitTypeBR         = "br"
 | 
						|
	ExplicitTypeDumpling   = "dumpling"
 | 
						|
	ExplicitTypeBackground = "background"
 | 
						|
	ExplicitTypeDDL        = "ddl"
 | 
						|
	ExplicitTypeStats      = "stats"
 | 
						|
)
 | 
						|
 | 
						|
// ExplicitTypeList is the list of all explicit source types.
 | 
						|
var ExplicitTypeList = []string{ExplicitTypeEmpty, ExplicitTypeLightning, ExplicitTypeBR, ExplicitTypeDumpling, ExplicitTypeBackground, ExplicitTypeDDL, ExplicitTypeStats}
 | 
						|
 | 
						|
const (
 | 
						|
	// InternalRequest is the scope of internal queries
 | 
						|
	InternalRequest = "internal"
 | 
						|
	// InternalRequestPrefix is the prefix of internal queries
 | 
						|
	InternalRequestPrefix = "internal_"
 | 
						|
	// ExternalRequest is the scope of external queries
 | 
						|
	ExternalRequest = "external"
 | 
						|
	// SourceUnknown keeps same with the default value(empty string)
 | 
						|
	SourceUnknown = "unknown"
 | 
						|
)
 | 
						|
 | 
						|
// RequestSource contains the source label of the request, used for tracking resource consuming.
 | 
						|
type RequestSource struct {
 | 
						|
	RequestSourceInternal bool
 | 
						|
	RequestSourceType     string
 | 
						|
	// ExplicitRequestSourceType is a type that is set from the session variable and may be specified by the client or users.
 | 
						|
	// It is a complement to the RequestSourceType and provides additional information about how a request was initiated.
 | 
						|
	ExplicitRequestSourceType string
 | 
						|
}
 | 
						|
 | 
						|
// SetRequestSourceInternal sets the scope of the request source.
 | 
						|
func (r *RequestSource) SetRequestSourceInternal(internal bool) {
 | 
						|
	r.RequestSourceInternal = internal
 | 
						|
}
 | 
						|
 | 
						|
// SetRequestSourceType sets the type of the request source.
 | 
						|
func (r *RequestSource) SetRequestSourceType(tp string) {
 | 
						|
	r.RequestSourceType = tp
 | 
						|
}
 | 
						|
 | 
						|
// SetExplicitRequestSourceType sets the type of the request source.
 | 
						|
func (r *RequestSource) SetExplicitRequestSourceType(tp string) {
 | 
						|
	r.ExplicitRequestSourceType = tp
 | 
						|
}
 | 
						|
 | 
						|
// WithInternalSourceType create context with internal source.
 | 
						|
func WithInternalSourceType(ctx context.Context, source string) context.Context {
 | 
						|
	return context.WithValue(ctx, RequestSourceKey, RequestSource{
 | 
						|
		RequestSourceInternal: true,
 | 
						|
		RequestSourceType:     source,
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// WithInternalSourceAndTaskType create context with internal source and task name.
 | 
						|
func WithInternalSourceAndTaskType(ctx context.Context, source, taskName string) context.Context {
 | 
						|
	return context.WithValue(ctx, RequestSourceKey, RequestSource{
 | 
						|
		RequestSourceInternal:     true,
 | 
						|
		RequestSourceType:         source,
 | 
						|
		ExplicitRequestSourceType: taskName,
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
// BuildRequestSource builds a request_source from internal, source and explicitSource.
 | 
						|
func BuildRequestSource(internal bool, source, explicitSource string) string {
 | 
						|
	requestSource := RequestSource{
 | 
						|
		RequestSourceInternal:     internal,
 | 
						|
		RequestSourceType:         source,
 | 
						|
		ExplicitRequestSourceType: explicitSource,
 | 
						|
	}
 | 
						|
	return requestSource.GetRequestSource()
 | 
						|
}
 | 
						|
 | 
						|
// IsRequestSourceInternal checks whether the input request source type is internal type.
 | 
						|
func IsRequestSourceInternal(reqSrc *RequestSource) bool {
 | 
						|
	isInternal := false
 | 
						|
	if reqSrc != nil && IsInternalRequest(reqSrc.GetRequestSource()) {
 | 
						|
		isInternal = true
 | 
						|
	}
 | 
						|
	return isInternal
 | 
						|
}
 | 
						|
 | 
						|
// GetRequestSource gets the request_source field of the request.
 | 
						|
func (r *RequestSource) GetRequestSource() string {
 | 
						|
	source := SourceUnknown
 | 
						|
	origin := ExternalRequest
 | 
						|
	if r == nil || (len(r.RequestSourceType) == 0 && len(r.ExplicitRequestSourceType) == 0) {
 | 
						|
		// if r.RequestSourceType and r.ExplicitRequestSourceType are not set, it's mostly possible that r.RequestSourceInternal is not set
 | 
						|
		// to avoid internal requests be marked as external(default value), return unknown source here.
 | 
						|
		return source
 | 
						|
	}
 | 
						|
	if r.RequestSourceInternal {
 | 
						|
		origin = InternalRequest
 | 
						|
	}
 | 
						|
	labelList := make([]string, 0, 3)
 | 
						|
	labelList = append(labelList, origin)
 | 
						|
	if len(r.RequestSourceType) > 0 {
 | 
						|
		source = r.RequestSourceType
 | 
						|
	}
 | 
						|
	labelList = append(labelList, source)
 | 
						|
	if len(r.ExplicitRequestSourceType) > 0 && r.ExplicitRequestSourceType != r.RequestSourceType {
 | 
						|
		labelList = append(labelList, r.ExplicitRequestSourceType)
 | 
						|
	}
 | 
						|
 | 
						|
	return strings.Join(labelList, "_")
 | 
						|
}
 | 
						|
 | 
						|
// RequestSourceFromCtx extract source from passed context.
 | 
						|
func RequestSourceFromCtx(ctx context.Context) string {
 | 
						|
	if source := ctx.Value(RequestSourceKey); source != nil {
 | 
						|
		rs := source.(RequestSource)
 | 
						|
		return rs.GetRequestSource()
 | 
						|
	}
 | 
						|
	return SourceUnknown
 | 
						|
}
 | 
						|
 | 
						|
// IsInternalRequest returns the type of the request source.
 | 
						|
func IsInternalRequest(source string) bool {
 | 
						|
	return strings.HasPrefix(source, InternalRequest)
 | 
						|
}
 | 
						|
 | 
						|
// ResourceGroupNameKeyType is the context key type of resource group name.
 | 
						|
type resourceGroupNameKeyType struct{}
 | 
						|
 | 
						|
// ResourceGroupNameKey is used as the key of request source type in context.
 | 
						|
var resourceGroupNameKey = resourceGroupNameKeyType{}
 | 
						|
 | 
						|
// WithResourceGroupName return a copy of the given context with a associated
 | 
						|
// resource group name.
 | 
						|
func WithResourceGroupName(ctx context.Context, groupName string) context.Context {
 | 
						|
	return context.WithValue(ctx, resourceGroupNameKey, groupName)
 | 
						|
}
 | 
						|
 | 
						|
// ResourceGroupNameFromCtx extract resource group name from passed context,
 | 
						|
// empty string is returned is the key is not set.
 | 
						|
func ResourceGroupNameFromCtx(ctx context.Context) string {
 | 
						|
	if val := ctx.Value(resourceGroupNameKey); val != nil {
 | 
						|
		return val.(string)
 | 
						|
	}
 | 
						|
	return ""
 | 
						|
}
 |