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 }