-
Notifications
You must be signed in to change notification settings - Fork 220
/
request_source.go
187 lines (161 loc) · 6.58 KB
/
request_source.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// 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 ""
}