xframe/vendor/github.com/polarismesh/polaris-go/pkg/config/plugin.go

201 lines
6.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Tencent is pleased to support the open source community by making polaris-go available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 config
import (
"fmt"
"reflect"
"time"
"github.com/hashicorp/go-multierror"
"github.com/modern-go/reflect2"
"gopkg.in/yaml.v2"
"github.com/polarismesh/polaris-go/pkg/plugin/common"
)
// 插件配置类型
var pluginConfigTypes = make(map[common.Type]map[string]reflect.Type)
// RegisterPluginConfigType RegisterPlugin 注册插件到全局配置对象,并注册插件配置类型.
func RegisterPluginConfigType(typ common.Type, name string, cfg BaseConfig) {
if reflect2.IsNil(cfg) {
return
}
cfgTypes, exists := pluginConfigTypes[typ]
if !exists {
cfgTypes = make(map[string]reflect.Type)
pluginConfigTypes[typ] = cfgTypes
}
cfgTypes[name] = reflect.TypeOf(cfg).Elem()
}
// ErrorCountConfig 连续错误数熔断配置.
type ErrorCountConfig interface {
// GetContinuousErrorThreshold 连续错误数阈值
GetContinuousErrorThreshold() int
// SetContinuousErrorThreshold 设置连续错误数阈值
SetContinuousErrorThreshold(int)
// GetMetricStatTimeWindow 连续错误数统计时间窗口
GetMetricStatTimeWindow() time.Duration
// SetMetricStatTimeWindow 设置连续错误数统计时间窗口
SetMetricStatTimeWindow(time.Duration)
// GetMetricNumBuckets 连续错误数统计滑桶数量
GetMetricNumBuckets() int
// SetMetricNumBuckets 设置连续错误数统计滑桶数量
SetMetricNumBuckets(int)
// GetBucketInterval 获取单个滑桶的时间间隔
GetBucketInterval() time.Duration
}
// ErrorRateConfig 错误率熔断配置.
type ErrorRateConfig interface {
// GetRequestVolumeThreshold 触发错误率熔断的请求量阈值
GetRequestVolumeThreshold() int
// SetRequestVolumeThreshold 设置触发错误率熔断的请求量阈值
SetRequestVolumeThreshold(int)
// GetErrorRatePercent 触发熔断的错误率阈值,取值范围(0, 100]
GetErrorRatePercent() int
// SetErrorRatePercent 设置错误率阈值
SetErrorRatePercent(int)
// GetMetricStatTimeWindow 错误率统计时间窗口
GetMetricStatTimeWindow() time.Duration
// SetMetricStatTimeWindow 设置错误率统计时间窗口
SetMetricStatTimeWindow(time.Duration)
// GetMetricNumBuckets 统计窗口细分的桶数量
GetMetricNumBuckets() int
// SetMetricNumBuckets 设置统计窗口细分的桶数量
SetMetricNumBuckets(int)
// GetBucketInterval 获取单个滑桶的时间间隔
GetBucketInterval() time.Duration
}
// PluginConfigs 插件配置实现类.
type PluginConfigs map[string]interface{}
// getPluginConfigTypes 获取插件配置类型,返回插件名到类型的映射.
func getPluginConfigTypes(typ common.Type) map[string]reflect.Type {
plugs, exists := pluginConfigTypes[typ]
if !exists {
return nil
}
return plugs
}
// getPluginConfigType 获取插件配置类型,具体插件类型.
func getPluginConfigType(typ common.Type, name string) (reflect.Type, bool) {
plugs, exists := pluginConfigTypes[typ]
if !exists {
return nil, false
}
if plugCfg, ok := plugs[name]; ok {
return plugCfg, ok
}
return nil, false
}
// Init 初始化配置对象.
func (p PluginConfigs) Init(typ common.Type) {
cfgTypes := getPluginConfigTypes(typ)
for name, cfgType := range cfgTypes {
value := reflect.New(cfgType).Interface()
p[name] = value
}
}
// convertFromTextValues 对于从yaml/json加载的结构做一个转换.
func convertFromTextValues(cfgType reflect.Type, cfgValue interface{}) BaseConfig {
// 如果在配置文件中没有相关内容,直接创建一个配置对象返回即可
if reflect2.IsNil(cfgValue) {
return reflect.New(cfgType).Interface().(BaseConfig)
}
var jsonValues map[interface{}]interface{}
var ok bool
if jsonValues, ok = cfgValue.(map[interface{}]interface{}); !ok {
return cfgValue.(BaseConfig)
}
configValue := reflect.New(cfgType).Interface()
buf, _ := yaml.Marshal(jsonValues)
_ = yaml.Unmarshal(buf, configValue)
return configValue.(BaseConfig)
}
// SetDefault 设置默认值.
func (p PluginConfigs) SetDefault(typ common.Type) {
for plugName := range p {
// 如果不是注册进来的配置项从PluginConfigs里面删除掉
if _, exists := getPluginConfigType(typ, plugName); !exists {
delete(p, plugName)
continue
}
}
configTypes := getPluginConfigTypes(typ)
if configTypes == nil {
return
}
for pluginName, configType := range configTypes {
cfg := convertFromTextValues(configType, p[pluginName])
cfg.SetDefault()
p[pluginName] = cfg
}
}
// Verify 校验插件配置.
func (p PluginConfigs) Verify() error {
for name, cfgValue := range p {
cfg, ok := cfgValue.(BaseConfig)
if !ok {
continue
}
// 检验插件配置
if err := cfg.Verify(); err != nil {
return fmt.Errorf("fail to verify plugin %s config, err is %v", name, err)
}
}
return nil
}
// SetPluginConfig 设置单独一个插件的值.
func (p PluginConfigs) SetPluginConfig(plugType common.Type, plugName string, value BaseConfig) error {
configType, exists := getPluginConfigType(plugType, plugName)
if !exists {
return fmt.Errorf("config not registered for plugin(type %s, name %s)", plugType, plugName)
}
valueType := reflect.TypeOf(value).Elem()
if valueType != configType {
return fmt.Errorf("type %s not match config type %s for plugin(type %s, name %s)",
valueType, configType, plugType, plugName)
}
value.SetDefault()
err := value.Verify()
if err != nil {
return multierror.Prefix(err, "Fail to verify config value of "+plugType.String()+":"+plugName+": ")
}
p[plugName] = value
return nil
}
// GetPluginConfig 根据插件名获取配置.
func (p PluginConfigs) GetPluginConfig(pluginName string) BaseConfig {
cfg, ok := p[pluginName]
if !ok {
return nil
}
return cfg.(BaseConfig)
}