github.com/Rookout/GoSDK@v0.1.48/pkg/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"strconv"
     7  	"sync"
     8  	"sync/atomic"
     9  	"time"
    10  
    11  	"github.com/Rookout/GoSDK/pkg/utils"
    12  )
    13  
    14  var configLock sync.Mutex
    15  var config atomic.Value
    16  
    17  func init() {
    18  	config.Store(GetDefaultConfiguration())
    19  }
    20  
    21  func AgentComWsConfig() AgentComWsConfiguration {
    22  	c := config.Load().(DynamicConfiguration)
    23  	return c.AgentComWsConfiguration
    24  }
    25  func LocationsConfig() LocationsConfiguration {
    26  	c := config.Load().(DynamicConfiguration)
    27  	return c.LocationsConfiguration
    28  }
    29  func LoggingConfig() LoggingConfiguration {
    30  	c := config.Load().(DynamicConfiguration)
    31  	return c.LoggingConfiguration
    32  }
    33  func OutputWsConfig() OutputWsConfiguration {
    34  	c := config.Load().(DynamicConfiguration)
    35  	return c.OutputWsConfiguration
    36  }
    37  func RateLimiterConfig() RateLimiterConfiguration {
    38  	c := config.Load().(DynamicConfiguration)
    39  	return c.RateLimiterConfiguration
    40  }
    41  func BackoffConfig() BackoffConfiguration {
    42  	c := config.Load().(DynamicConfiguration)
    43  	return c.BackoffConfiguration
    44  }
    45  func WebSocketClientConfig() WebSocketClientConfiguration {
    46  	c := config.Load().(DynamicConfiguration)
    47  	return c.WebSocketClientConfiguration
    48  }
    49  func SizeLimitedChannelConfig() SizeLimitedChannelConfiguration {
    50  	c := config.Load().(DynamicConfiguration)
    51  	return c.SizeLimitedChannelConfiguration
    52  }
    53  
    54  type LocationsConfiguration struct {
    55  	MaxAugTime           time.Duration
    56  	MaxAugTimeMultiplier float64
    57  }
    58  
    59  type RateLimiterConfiguration struct {
    60  	MinRateLimitValue           time.Duration
    61  	GlobalRateLimitQuotaMS      string
    62  	GlobalRateLimitWindowSizeMS string
    63  	GlobalRateLimit             string
    64  }
    65  
    66  type LoggingConfiguration struct {
    67  	FileName    string
    68  	LogToStderr bool
    69  	LogLevel    string
    70  	Debug       bool
    71  	MaxLogSize  int
    72  	Quiet       bool
    73  }
    74  
    75  type AgentComWsConfiguration struct {
    76  	PingTimeout       time.Duration
    77  	ConnectTimeout    time.Duration
    78  	ConnectionTimeout time.Duration
    79  }
    80  
    81  type BackoffConfiguration struct {
    82  	DefaultBackoff      time.Duration
    83  	MaxBackoff          time.Duration
    84  	ResetBackoffTimeout time.Duration
    85  }
    86  
    87  type ObjectDumpConfigDefaults struct {
    88  	defaultConfig   ObjectDumpConfig
    89  	tolerantConfig  ObjectDumpConfig
    90  	strictConfig    ObjectDumpConfig
    91  	unlimitedConfig ObjectDumpConfig
    92  }
    93  
    94  type SizeLimitedChannelConfiguration struct {
    95  	FlushTimeout      time.Duration
    96  	MaxQueueLength    int
    97  	MaxBytesInChannel int
    98  	MaxMessageSize    int
    99  }
   100  
   101  type OutputWsConfiguration struct {
   102  	MaxStatusUpdates  int
   103  	BucketRefreshRate int
   104  	MaxAugMessages    int
   105  	MaxLogItems       int
   106  	ProtobufVersion2  bool
   107  }
   108  
   109  type WebSocketClientConfiguration struct {
   110  	PingTimeout   time.Duration
   111  	PingInterval  time.Duration
   112  	WriteTimeout  time.Duration
   113  	SkipSSLVerify bool
   114  }
   115  
   116  type DynamicConfiguration struct {
   117  	AgentComWsConfiguration         AgentComWsConfiguration
   118  	LocationsConfiguration          LocationsConfiguration
   119  	LoggingConfiguration            LoggingConfiguration
   120  	OutputWsConfiguration           OutputWsConfiguration
   121  	RateLimiterConfiguration        RateLimiterConfiguration
   122  	BackoffConfiguration            BackoffConfiguration
   123  	WebSocketClientConfiguration    WebSocketClientConfiguration
   124  	SizeLimitedChannelConfiguration SizeLimitedChannelConfiguration
   125  
   126  	ObjectDumpConfigDefaults ObjectDumpConfigDefaults
   127  	onUpdate                 []func()
   128  }
   129  
   130  func GetDefaultConfiguration() DynamicConfiguration {
   131  	return DynamicConfiguration{
   132  		LocationsConfiguration: LocationsConfiguration{
   133  			MaxAugTime:           400 * time.Millisecond,
   134  			MaxAugTimeMultiplier: 1,
   135  		},
   136  		RateLimiterConfiguration: RateLimiterConfiguration{
   137  			MinRateLimitValue:           20000 * time.Nanosecond,
   138  			GlobalRateLimit:             os.Getenv("ROOKOUT_GLOBAL_RATE_LIMIT"),
   139  			GlobalRateLimitQuotaMS:      "",
   140  			GlobalRateLimitWindowSizeMS: "",
   141  		},
   142  		LoggingConfiguration: LoggingConfiguration{
   143  			FileName:    "",
   144  			LogToStderr: false,
   145  			LogLevel:    "INFO",
   146  			Debug:       false,
   147  			Quiet:       false,
   148  			MaxLogSize:  100 * 1024 * 1024, 
   149  		},
   150  		AgentComWsConfiguration: AgentComWsConfiguration{
   151  			ConnectTimeout:    10 * time.Minute,
   152  			PingTimeout:       10 * time.Second,
   153  			ConnectionTimeout: 8 * time.Second,
   154  		},
   155  		SizeLimitedChannelConfiguration: SizeLimitedChannelConfiguration{
   156  			FlushTimeout:      2 * time.Second,
   157  			MaxQueueLength:    250,
   158  			MaxBytesInChannel: 15 * 1024 * 1024,
   159  			MaxMessageSize:    1024 * 1024,
   160  		},
   161  		BackoffConfiguration: BackoffConfiguration{
   162  			DefaultBackoff:      200 * time.Millisecond,
   163  			MaxBackoff:          60 * time.Second,
   164  			ResetBackoffTimeout: 3 * time.Minute,
   165  		},
   166  		WebSocketClientConfiguration: WebSocketClientConfiguration{
   167  			PingTimeout:   30 * time.Second,
   168  			PingInterval:  10 * time.Second,
   169  			WriteTimeout:  5 * time.Second,
   170  			SkipSSLVerify: utils.IsTrue(os.Getenv("ROOKOUT_SKIP_SSL_VERIFY")),
   171  		},
   172  		ObjectDumpConfigDefaults: ObjectDumpConfigDefaults{
   173  			unlimitedConfig: ObjectDumpConfig{
   174  				MaxDepth:           0,
   175  				MaxWidth:           100,
   176  				MaxCollectionDepth: 0,
   177  				MaxString:          64 * 1024,
   178  			},
   179  			defaultConfig: ObjectDumpConfig{
   180  				MaxDepth:           4,
   181  				MaxWidth:           15,
   182  				MaxCollectionDepth: 4,
   183  				MaxString:          512,
   184  			},
   185  			tolerantConfig: ObjectDumpConfig{
   186  				MaxDepth:           5,
   187  				MaxWidth:           25,
   188  				MaxCollectionDepth: 5,
   189  				MaxString:          4 * 1024,
   190  			},
   191  			strictConfig: ObjectDumpConfig{
   192  				MaxDepth:           2,
   193  				MaxWidth:           10,
   194  				MaxCollectionDepth: 2,
   195  				MaxString:          128,
   196  			},
   197  		},
   198  		OutputWsConfiguration: OutputWsConfiguration{
   199  			MaxStatusUpdates:  200,
   200  			BucketRefreshRate: 10,
   201  			MaxAugMessages:    250,
   202  			MaxLogItems:       200,
   203  			ProtobufVersion2:  utils.IsTrue(os.Getenv("ROOKOUT_Protobuf_Version2")),
   204  		},
   205  	}
   206  }
   207  
   208  func updateGlobalRateLimitConfig(newConfig *DynamicConfiguration) {
   209  	if os.Getenv("ROOKOUT_GLOBAL_RATE_LIMIT") != "" {
   210  		return
   211  	}
   212  
   213  	config := RateLimiterConfig()
   214  	if config.GlobalRateLimit == "" {
   215  		if config.GlobalRateLimitQuotaMS != "" &&
   216  			config.GlobalRateLimitWindowSizeMS != "" {
   217  			newConfig.RateLimiterConfiguration.GlobalRateLimit = fmt.Sprintf("%s/%s",
   218  				config.GlobalRateLimitQuotaMS,
   219  				config.GlobalRateLimitWindowSizeMS,
   220  			)
   221  		}
   222  	}
   223  }
   224  
   225  var configParsers = map[string]func(string, *DynamicConfiguration){
   226  	"GOLANG_DEFAULT_MAX_DEPTH": func(value string, config *DynamicConfiguration) {
   227  		defaultMaxDepth, err := strconv.Atoi(value)
   228  		if err != nil {
   229  			return
   230  		}
   231  
   232  		config.ObjectDumpConfigDefaults.defaultConfig.MaxDepth = defaultMaxDepth
   233  	},
   234  	"GOLANG_DEFAULT_MAX_COLLECTION_DEPTH": func(value string, config *DynamicConfiguration) {
   235  		defaultMaxCollectionDepth, err := strconv.Atoi(value)
   236  		if err != nil {
   237  			return
   238  		}
   239  
   240  		config.ObjectDumpConfigDefaults.defaultConfig.MaxCollectionDepth = defaultMaxCollectionDepth
   241  	},
   242  	"GOLANG_TOLERANT_MAX_DEPTH": func(value string, config *DynamicConfiguration) {
   243  		tolerantMaxDepth, err := strconv.Atoi(value)
   244  		if err != nil {
   245  			return
   246  		}
   247  
   248  		config.ObjectDumpConfigDefaults.tolerantConfig.MaxDepth = tolerantMaxDepth
   249  	},
   250  	"GOLANG_TOLERANT_MAX_WIDTH": func(value string, config *DynamicConfiguration) {
   251  		tolerantMaxWidth, err := strconv.Atoi(value)
   252  		if err != nil {
   253  			return
   254  		}
   255  
   256  		config.ObjectDumpConfigDefaults.tolerantConfig.MaxCollectionDepth = tolerantMaxWidth
   257  	},
   258  	"GOLANG_MAX_MESSAGE_SIZE": func(value string, config *DynamicConfiguration) {
   259  		maxMessageSize, err := strconv.Atoi(value)
   260  		if err != nil {
   261  			return
   262  		}
   263  
   264  		config.SizeLimitedChannelConfiguration.MaxMessageSize = maxMessageSize
   265  		config.SizeLimitedChannelConfiguration.MaxQueueLength = maxMessageSize * 10
   266  	},
   267  	"GOLANG_MAX_AUG_TIME_MULTIPLIER": func(value string, config *DynamicConfiguration) {
   268  		maxAugTimeMultiplier, err := strconv.ParseFloat(value, 64)
   269  		if err != nil {
   270  			return
   271  		}
   272  
   273  		if maxAugTimeMultiplier > 2 || maxAugTimeMultiplier < 1 {
   274  			
   275  			return
   276  		}
   277  
   278  		config.LocationsConfiguration.MaxAugTimeMultiplier = maxAugTimeMultiplier
   279  	},
   280  	"GOLANG_GLOBAL_RATE_LIMIT_QUOTA_MS": func(value string, config *DynamicConfiguration) {
   281  		if config.RateLimiterConfiguration.GlobalRateLimit == "" {
   282  			config.RateLimiterConfiguration.GlobalRateLimitQuotaMS = value
   283  
   284  			if config.RateLimiterConfiguration.GlobalRateLimitWindowSizeMS != "" {
   285  				config.RateLimiterConfiguration.GlobalRateLimit = fmt.Sprintf("%s/%s",
   286  					config.RateLimiterConfiguration.GlobalRateLimitQuotaMS,
   287  					config.RateLimiterConfiguration.GlobalRateLimitWindowSizeMS)
   288  			}
   289  		}
   290  	},
   291  	"GOLANG_GLOBAL_RATE_LIMIT_WINDOW_SIZE_MS": func(value string, config *DynamicConfiguration) {
   292  		if config.RateLimiterConfiguration.GlobalRateLimit == "" {
   293  			config.RateLimiterConfiguration.GlobalRateLimitWindowSizeMS = value
   294  
   295  			if config.RateLimiterConfiguration.GlobalRateLimitQuotaMS != "" {
   296  				config.RateLimiterConfiguration.GlobalRateLimit = fmt.Sprintf("%s/%s",
   297  					config.RateLimiterConfiguration.GlobalRateLimitQuotaMS,
   298  					config.RateLimiterConfiguration.GlobalRateLimitWindowSizeMS)
   299  			}
   300  		}
   301  	},
   302  	"GOLANG_PROTOBUF_VERSION_2": func(value string, config *DynamicConfiguration) {
   303  		if value == "" {
   304  			return
   305  		}
   306  
   307  		config.OutputWsConfiguration.ProtobufVersion2 = config.OutputWsConfiguration.ProtobufVersion2 || utils.Contains(utils.TrueValues, value)
   308  	},
   309  }
   310  
   311  
   312  
   313  func UpdateConfig(update func(config *DynamicConfiguration)) {
   314  	configLock.Lock()
   315  	defer configLock.Unlock()
   316  
   317  	c := config.Load().(DynamicConfiguration)
   318  	update(&c)
   319  	config.Store(c)
   320  
   321  	for _, f := range c.onUpdate {
   322  		f()
   323  	}
   324  }
   325  
   326  func Update(configMap map[string]string) {
   327  	UpdateConfig(func(config *DynamicConfiguration) {
   328  		for key, f := range configParsers {
   329  			if value, ok := configMap[key]; ok {
   330  				f(value, config)
   331  			}
   332  		}
   333  		updateGlobalRateLimitConfig(config)
   334  	})
   335  }
   336  
   337  func OnUpdate(f func()) {
   338  	UpdateConfig(func(config *DynamicConfiguration) {
   339  		config.onUpdate = append(config.onUpdate, f)
   340  	})
   341  }