Thanos源码专题【左扬精讲】——Thanos API 组件(release-0.26)源码阅读和分析(详解 pkg\api\api.go)
Thanos API 组件(release-0.26)源码阅读和分析(详解 pkg\api\api.go)
https://github.com/thanos-io/thanos/blob/v0.26.0/pkg/api/api.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 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 | // Copyright (c) The Thanos Authors. // Licensed under the Apache License 2.0. // Copyright 2016 The Prometheus 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. // This package is a modified copy from // github.com/prometheus/prometheus/web/api/v1@2121b4628baa7d9d9406aa468712a6a332e77aff. package api import ( "encoding/json" // for json.Marshal "fmt" // for fmt.Errorf "net/http" // for http.Server "os" // for os.Exit "runtime" // for runtime.NumCPU "time" // for time.Duration "github.com/NYTimes/gziphandler" // for gziphandler.GzipHandler "github.com/go-kit/log" // for log.Logger "github.com/go-kit/log/level" // for level.Info "github.com/opentracing/opentracing-go" // for opentracing.Tracer "github.com/prometheus/common/route" // for route.NewRoute "github.com/prometheus/common/version" // for version.Version extpromhttp "github.com/thanos-io/thanos/pkg/extprom/http" // for extpromhttp.MetricsHandler "github.com/thanos-io/thanos/pkg/logging" // for logging.WithContext "github.com/thanos-io/thanos/pkg/server/http/middleware" // for middleware.Tracing "github.com/thanos-io/thanos/pkg/tracing" // for tracing.Tracer ) type status string const ( StatusSuccess status = "success" StatusError status = "error" ) type ErrorType string const ( ErrorNone ErrorType = "" ErrorTimeout ErrorType = "timeout" // 超时错误 ErrorCanceled ErrorType = "canceled" // 取消错误 ErrorExec ErrorType = "execution" // 执行错误 ErrorBadData ErrorType = "bad_data" // 错误数据 ErrorInternal ErrorType = "internal" // 内部错误 ) // corsHeaders 是 CORS 头部的默认值。 var corsHeaders = map [string]string{ "Access-Control-Allow-Headers" : "Accept, Accept-Encoding, Authorization, Content-Type, Origin" , "Access-Control-Allow-Methods" : "GET, OPTIONS" , "Access-Control-Allow-Origin" : "*" , "Access-Control-Expose-Headers" : "Date" , } // ThanosVersion contains build information about Thanos. // ThanosVersion 包含构建信息。比如版本号、修订版、分支、构建用户、构建日期、Go版本。 type ThanosVersion struct { Version string `json: "version" ` // 版本号 Revision string `json: "revision" ` // 修订版 Branch string `json: "branch" ` // 分支 BuildUser string `json: "buildUser" ` // 构建用户 BuildDate string `json: "buildDate" ` // 构建日期 GoVersion string `json: "goVersion" ` // Go版本号 } // BuildInfo 是初始化的 ThanosVersion 对象。 var BuildInfo = &ThanosVersion{ Version: version.Version, // 版本号,比如 v0.18.0 Revision: version.Revision, // 修订版,比如 123456789abcdef0 Branch: version.Branch, // 分支,比如 master BuildUser: version.BuildUser, // 构建用户,比如 root@localhost BuildDate: version.BuildDate, // 构建日期,比如 2020-01-01T00:00:00Z GoVersion: version.GoVersion, // Go的版本号,比如 go-v1.24.0 } type ApiError struct { Typ ErrorType Err error } // Error 返回API错误的字符串表示。 // 使用fmt.Sprintf格式化字符串,将e.Typ和e.Err拼接成一个错误消息。 func (e *ApiError) Error() string { // 使用fmt.Sprintf格式化字符串,将e.Typ和e.Err拼接成一个错误消息 return fmt.Sprintf( "%s: %s" , e.Typ, e.Err) } // RuntimeInfo contains runtime information about Thanos. type RuntimeInfo struct { StartTime time.Time `json: "startTime" ` // 启动时间 CWD string `json: "CWD" ` // 当前工作目录 GoroutineCount int `json: "goroutineCount" ` // 协程数量 GOMAXPROCS int `json: "GOMAXPROCS" ` // GOMAXPROCS的值,表示可以同时运行的协程数量 GOGC string `json: "GOGC" ` // GOGC的值,表示垃圾回收的目标百分比 GODEBUG string `json: "GODEBUG" ` // GODEBUG的值,表示调试标志 } // RuntimeInfoFn returns updated runtime information about Thanos. // 返回一个RuntimeInfo结构体,包含Thanos的运行时信息。 type RuntimeInfoFn func () RuntimeInfo type response struct { Status status `json: "status" ` // 状态,比如 "success" 或 "error" Data interface {} `json: "data,omitempty" ` // 数据,比如查询结果 ErrorType ErrorType `json: "errorType,omitempty" ` // 错误类型,比如 "timeout" 或 "internal" Error string `json: "error,omitempty" ` // 错误信息,比如 "timeout: context canceled" Warnings []string `json: "warnings,omitempty" ` // 警告信息,比如 "some warning" } // SetCORS enables cross-site script calls. // SetCORS 函数用于设置跨源资源共享(CORS)相关的响应头。 // // 参数: // w http.ResponseWriter: 用于写入响应的HTTP响应写入器。 func SetCORS(w http.ResponseWriter) { // 遍历 corsHeaders 映射 for h, v := range corsHeaders { // 设置响应头,键为 h,值为 v w.Header().Set(h, v) } } // ApiFunc 是一个函数类型,用于处理HTTP请求,并返回响应数据、警告信息以及可能的错误。 type ApiFunc func (r *http.Request) ( interface {}, []error, *ApiError) // BaseAPI 是一个HTTP API的基础类型,用于处理HTTP请求,并返回响应数据、警告信息以及可能的错误。 type BaseAPI struct { logger log.Logger // 日志记录器,用于记录日志信息。 flagsMap map [string]string // 标志映射,用于存储命令行标志的值。 runtimeInfo RuntimeInfoFn // 运行时信息获取函数,用于获取Thanos的当前运行状态。 buildInfo *ThanosVersion // 构建信息,包含Thanos的版本、修订版等信息。 Now func () time.Time // 当前时间的获取函数,用于记录请求处理的时间。 disableCORS bool // 是否禁用CORS,如果为true,则不会设置CORS相关的响应头。 } // NewBaseAPI returns a new initialized BaseAPI type. // NewBaseAPI 创建一个新的 BaseAPI 实例 // // 参数: // // logger: 日志记录器 // disableCORS: 是否禁用CORS // flagsMap: 标志映射 // // 返回值: // // 返回一个指向 BaseAPI 实例的指针 func NewBaseAPI(logger log.Logger, disableCORS bool, flagsMap map [string]string) *BaseAPI { // 初始化BaseAPI结构体 return &BaseAPI{ // 日志记录器 logger: logger, // 标志映射 flagsMap: flagsMap, // 运行时信息获取函数 runtimeInfo: GetRuntimeInfoFunc(logger), // 构建信息 buildInfo: BuildInfo, // 是否禁用CORS disableCORS: disableCORS, // 获取当前时间函数 Now: time.Now, } } // Register registers the common API endpoints. // Register 方法用于注册HTTP路由处理函数 // // 参数: // // r: HTTP路由对象 // tracer: OpenTracing的Tracer对象 // logger: 日志记录器对象 // ins: 仪器化中间件 // logMiddleware: HTTP服务器日志中间件 // // 说明: // // 该方法会将不同的HTTP请求路径和处理函数绑定到HTTP路由对象上。 // 通过仪器化中间件对请求进行监控和日志记录。 func (api *BaseAPI) Register(r *route.Router, tracer opentracing.Tracer, logger log.Logger, ins extpromhttp.InstrumentationMiddleware, logMiddleware *logging.HTTPServerMiddleware) { // 获取仪器化中间件 instr := GetInstr(tracer, logger, ins, logMiddleware, api.disableCORS) // 注册 OPTIONS 方法处理函数 r.Options( "/*path" , instr( "options" , api.options)) // 注册获取状态标志的方法处理函数 r.Get( "/status/flags" , instr( "status_flags" , api.flags)) // 注册获取运行时信息的方法处理函数 r.Get( "/status/runtimeinfo" , instr( "status_runtime" , api.serveRuntimeInfo)) // 注册获取构建信息的方法处理函数 r.Get( "/status/buildinfo" , instr( "status_build" , api.serveBuildInfo)) } // options 方法目前不执行任何操作,直接返回三个空值 // // 参数: // // r *http.Request: 传入的HTTP请求 // // 返回值: // // interface{}: 返回的接口类型的值,此处为空 // []error: 返回的错误列表,此处为空 // *ApiError: 返回的API错误信息,此处为空 func (api *BaseAPI) options(r *http.Request) ( interface {}, []error, *ApiError) { // 此函数目前不执行任何操作,直接返回三个空值 return nil, nil, nil } // flags 函数用于获取 BaseAPI 实例的 flagsMap。 // // 参数: // // r *http.Request: HTTP 请求对象,此参数在本函数中未被使用。 // // 返回值: // // interface{}: 返回 api 的 flagsMap。 // []error: 返回错误信息列表,本函数始终返回 nil。 // *ApiError: 返回 ApiError 对象,本函数始终返回 nil。 func (api *BaseAPI) flags(r *http.Request) ( interface {}, []error, *ApiError) { // 直接返回api的flagsMap,错误信息列表为空,ApiError为空 return api.flagsMap, nil, nil } // serveRuntimeInfo 处理HTTP请求,返回运行时信息 // // 参数: // // r *http.Request: HTTP请求对象 // // 返回值: // // interface{}: 返回的运行时信息 // []error: 错误列表,如果没有错误则返回nil // *ApiError: Api错误对象,如果没有错误则返回nil func (api *BaseAPI) serveRuntimeInfo(r *http.Request) ( interface {}, []error, *ApiError) { // 调用api的runtimeInfo方法获取运行时信息 return api.runtimeInfo(), nil, nil } // serveBuildInfo 是 BaseAPI 结构体的方法,用于处理 HTTP 请求并返回构建信息。 // // 参数: // // r *http.Request: 传入的 HTTP 请求对象。 // // 返回值: // // interface{}: 返回的构建信息,类型为 BaseAPI 结构体中的 buildInfo 字段。 // []error: 错误列表,本方法直接返回 nil,表示无错误。 // *ApiError: ApiError 指针,本方法直接返回 nil,表示无 ApiError。 func (api *BaseAPI) serveBuildInfo(r *http.Request) ( interface {}, []error, *ApiError) { // 直接返回buildInfo信息,无错误,也无ApiError return api.buildInfo, nil, nil } // GetRuntimeInfoFunc 返回一个返回 RuntimeInfo 类型的函数,该函数包含有关运行时信息。 // // 参数: // // logger: log.Logger 类型,用于记录日志 // // 返回值: // // RuntimeInfoFn 类型,一个返回 RuntimeInfo 类型的函数 func GetRuntimeInfoFunc(logger log.Logger) RuntimeInfoFn { // 获取当前工作目录 CWD, err := os.Getwd() if err != nil { // 如果获取当前工作目录失败,则将CWD设置为错误信息 CWD = "<error retrieving current working directory>" // 记录警告日志 level.Warn(logger).Log( "msg" , "failed to retrieve current working directory" , "err" , err) } // 记录程序启动时间 birth := time.Now() // 返回获取运行时信息的函数 return func () RuntimeInfo { return RuntimeInfo{ // 程序启动时间 StartTime: birth, // 当前工作目录 CWD: CWD, // 当前 Goroutine 数量 GoroutineCount: runtime.NumGoroutine(), // GOMAXPROCS 的值 GOMAXPROCS: runtime.GOMAXPROCS(0), // GOGC 的值 GOGC: os.Getenv( "GOGC" ), // GODEBUG 的值 GODEBUG: os.Getenv( "GODEBUG" ), } } } // InstrFunc 是一个函数类型,它接收一个字符串和一个 ApiFunc 作为参数,并返回一个 http.HandlerFunc。 type InstrFunc func (name string, f ApiFunc) http.HandlerFunc // GetInstr returns a http HandlerFunc with the instrumentation middleware. func GetInstr( tracer opentracing.Tracer, // OpenTracing的Tracer对象 logger log.Logger, // 日志记录器 ins extpromhttp.InstrumentationMiddleware, // Prometheus的InstrumentationMiddleware logMiddleware *logging.HTTPServerMiddleware, // 日志中间件 disableCORS bool, // 是否禁用CORS ) InstrFunc { instr := func (name string, f ApiFunc) http.HandlerFunc { // 定义HTTP处理函数 hf := http.HandlerFunc( func (w http.ResponseWriter, r *http.Request) { // 如果不禁用CORS,则设置CORS响应头 if !disableCORS { // 设置CORS响应头 SetCORS(w) } // 调用ApiFunc处理请求 if data, warnings, err := f(r); err != nil { // 如果发生错误,返回错误响应 RespondError(w, err, data) } else if data != nil { // 如果返回数据不为空,返回正常响应 Respond(w, data, warnings) } else { // 如果没有返回数据,返回204 No Content状态码 w.WriteHeader(http.StatusNoContent) } }) // 返回带有追踪功能的HTTP中间件 return tracing.HTTPMiddleware(tracer, name, logger, ins.NewHandler(name, // 使用gzip压缩处理 gziphandler.GzipHandler( // 使用RequestID中间件 middleware.RequestID( // 使用日志中间件处理 logMiddleware.HTTPMiddleware(name, hf), ), ), ), ) } return instr } // Respond 函数处理 HTTP 响应,将给定数据编码为 JSON 并返回给客户端。 // // 参数: // // w http.ResponseWriter: HTTP 响应写入器,用于发送响应数据。 // data interface{}: 要返回给客户端的数据。 // warnings []error: 警告信息列表,如果列表不为空,将设置 Cache-Control 为 no-store。 func Respond(w http.ResponseWriter, data interface {}, warnings []error) { // 设置响应头,指定内容类型为 application/json w.Header().Set( "Content-Type" , "application/json" ) // 如果存在警告信息,设置缓存控制为 no-store if len(warnings) > 0 { w.Header().Set( "Cache-Control" , "no-store" ) } // 设置 HTTP 状态码为 200 OK w.WriteHeader(http.StatusOK) // 初始化响应结构体 resp := &response{ Status: StatusSuccess, Data: data, } // 遍历警告信息,将其添加到响应结构体的警告列表中 for _, warn := range warnings { resp.Warnings = append(resp.Warnings, warn.Error()) } // 将响应结构体编码为 JSON 并写入响应体 _ = json.NewEncoder(w).Encode(resp) } // RespondError 函数用于处理错误响应 // // 参数: // - w http.ResponseWriter: HTTP 响应写入器 // - apiErr *ApiError: 封装了错误信息的结构体指针 // - data interface{}: 其他需要返回的数据 func RespondError(w http.ResponseWriter, apiErr *ApiError, data interface {}) { // 设置响应头的内容类型为 JSON w.Header().Set( "Content-Type" , "application/json" ) // 设置响应头禁止缓存 w.Header().Set( "Cache-Control" , "no-store" ) var code int switch apiErr.Typ { case ErrorBadData: // 数据错误,返回400 Bad Request code = http.StatusBadRequest case ErrorExec: // 执行错误,返回422 Unprocessable Entity code = 422 case ErrorCanceled, ErrorTimeout: // 请求被取消或超时,返回503 Service Unavailable code = http.StatusServiceUnavailable case ErrorInternal: // 内部错误,返回500 Internal Server Error code = http.StatusInternalServerError default : // 默认情况,返回500 Internal Server Error code = http.StatusInternalServerError } // 设置响应状态码 w.WriteHeader(code) // 使用 JSON 编码将响应数据写入响应体 _ = json.NewEncoder(w).Encode(&response{ // 状态码 Status: StatusError, // 错误类型 ErrorType: apiErr.Typ, // 错误信息 Error: apiErr.Err.Error(), // 其他数据 Data: data, }) } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析