Skip to content

Commit

Permalink
Add dynamic config change diff logging (#2494)
Browse files Browse the repository at this point in the history
* Add dynamic config change diff logging
  • Loading branch information
Ardagan committed Feb 23, 2022
1 parent 0c40243 commit 4c212e5
Show file tree
Hide file tree
Showing 12 changed files with 606 additions and 147 deletions.
100 changes: 98 additions & 2 deletions common/dynamicconfig/basic_client.go
Expand Up @@ -27,10 +27,12 @@ package dynamicconfig
import (
"errors"
"fmt"
"reflect"
"strings"
"sync/atomic"
"time"

"go.temporal.io/server/common/log"
"go.temporal.io/server/common/primitives/timestamp"
)

Expand All @@ -44,15 +46,28 @@ type constrainedValue struct {
}

type basicClient struct {
logger log.Logger
values atomic.Value // configValueMap
}

func newBasicClient() *basicClient {
bc := &basicClient{}
func newBasicClient(logger log.Logger) *basicClient {
bc := &basicClient{
logger: logger,
}
bc.values.Store(configValueMap{})
return bc
}

func (bc *basicClient) getValues() configValueMap {
return bc.values.Load().(configValueMap)
}

func (bc *basicClient) updateValues(newValues configValueMap) {
oldValues := bc.getValues()
bc.values.Store(newValues)
bc.logDiff(oldValues, newValues)
}

func (bc *basicClient) GetValue(
name Key,
defaultValue interface{},
Expand Down Expand Up @@ -210,3 +225,84 @@ func match(v *constrainedValue, filters map[Filter]interface{}) bool {
}
return true
}

func (fc *basicClient) logDiff(old configValueMap, new configValueMap) {
for key, newValues := range new {
oldValues, ok := old[key]
if !ok {
for _, newValue := range newValues {
// new key added
fc.logValueDiff(key, nil, newValue)
}
} else {
// compare existing keys
fc.logConstraintsDiff(key, oldValues, newValues)
}
}

// check for removed values
for key, oldValues := range old {
if _, ok := new[key]; !ok {
for _, oldValue := range oldValues {
fc.logValueDiff(key, oldValue, nil)
}
}
}
}

func (bc *basicClient) logConstraintsDiff(key string, oldValues []*constrainedValue, newValues []*constrainedValue) {
for _, oldValue := range oldValues {
matchFound := false
for _, newValue := range newValues {
if reflect.DeepEqual(oldValue.Constraints, newValue.Constraints) {
matchFound = true
if !reflect.DeepEqual(oldValue.Value, newValue.Value) {
bc.logValueDiff(key, oldValue, newValue)
}
}
}
if !matchFound {
bc.logValueDiff(key, oldValue, nil)
}
}

for _, newValue := range newValues {
matchFound := false
for _, oldValue := range oldValues {
if reflect.DeepEqual(oldValue.Constraints, newValue.Constraints) {
matchFound = true
}
}
if !matchFound {
bc.logValueDiff(key, nil, newValue)
}
}
}

func (bc *basicClient) logValueDiff(key string, oldValue *constrainedValue, newValue *constrainedValue) {
logLine := &strings.Builder{}
logLine.Grow(128)
logLine.WriteString("dynamic config changed for the key: ")
logLine.WriteString(key)
logLine.WriteString(" oldValue: ")
bc.appendConstrainedValue(logLine, oldValue)
logLine.WriteString(" newValue: ")
bc.appendConstrainedValue(logLine, newValue)
bc.logger.Info(logLine.String())
}

func (bc *basicClient) appendConstrainedValue(logLine *strings.Builder, value *constrainedValue) {
if value == nil {
logLine.WriteString("nil")
} else {
logLine.WriteString("{ constraints: {")
for constraintKey, constraintValue := range value.Constraints {
logLine.WriteString("{")
logLine.WriteString(constraintKey)
logLine.WriteString(":")
logLine.WriteString(fmt.Sprintf("%v", constraintValue))
logLine.WriteString("}")
}
logLine.WriteString(fmt.Sprint("} value: ", value.Value, " }"))
}
}
73 changes: 26 additions & 47 deletions common/dynamicconfig/config.go
Expand Up @@ -25,8 +25,6 @@
package dynamicconfig

import (
"reflect"
"sync"
"sync/atomic"
"time"

Expand All @@ -36,6 +34,15 @@ import (
"go.temporal.io/server/common/log/tag"
)

// Collection wraps dynamic config client with a closure so that across the code, the config values
// can be directly accessed by calling the function without propagating the client everywhere in
// code
type Collection struct {
client Client
logger log.Logger
errCount int64
}

const (
errCountLogThreshold = 1000
)
Expand All @@ -45,21 +52,10 @@ func NewCollection(client Client, logger log.Logger) *Collection {
return &Collection{
client: client,
logger: logger,
keys: &sync.Map{},
errCount: -1,
}
}

// Collection wraps dynamic config client with a closure so that across the code, the config values
// can be directly accessed by calling the function without propagating the client everywhere in
// code
type Collection struct {
client Client
logger log.Logger
keys *sync.Map // map of config Key to strongly typed value
errCount int64
}

func (c *Collection) logError(key Key, err error) {
errCount := atomic.AddInt64(&c.errCount, 1)
if errCount%errCountLogThreshold == 0 {
Expand All @@ -68,18 +64,6 @@ func (c *Collection) logError(key Key, err error) {
}
}

func (c *Collection) logValue(
key Key,
value, defaultValue interface{},
cmpValueEquals func(interface{}, interface{}) bool,
) {
cachedValue, isInCache := c.keys.Load(key)
if !isInCache || !cmpValueEquals(cachedValue, value) {
c.keys.Store(key, value)
c.logger.Info("Get dynamic config", tag.Name(key.String()), tag.Value(value), tag.DefaultValue(defaultValue))
}
}

// PropertyFn is a wrapper to get property from dynamic config
type PropertyFn func() interface{}

Expand Down Expand Up @@ -153,7 +137,6 @@ func (c *Collection) GetProperty(key Key, defaultValue interface{}) PropertyFn {
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, reflect.DeepEqual)
return val
}
}
Expand All @@ -174,7 +157,7 @@ func (c *Collection) GetIntProperty(key Key, defaultValue int) IntPropertyFn {
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, intCompareEquals)

return val
}
}
Expand All @@ -186,7 +169,7 @@ func (c *Collection) GetIntPropertyFilteredByNamespace(key Key, defaultValue int
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, intCompareEquals)

return val
}
}
Expand Down Expand Up @@ -217,7 +200,6 @@ func (c *Collection) GetIntPropertyFilteredByTaskQueueInfo(key Key, defaultValue
}
}

c.logValue(key, val, defaultValue, intCompareEquals)
return val
}
}
Expand All @@ -233,7 +215,7 @@ func (c *Collection) GetIntPropertyFilteredByShardID(key Key, defaultValue int)
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, intCompareEquals)

return val
}
}
Expand All @@ -245,7 +227,7 @@ func (c *Collection) GetFloat64Property(key Key, defaultValue float64) FloatProp
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, float64CompareEquals)

return val
}
}
Expand All @@ -261,7 +243,7 @@ func (c *Collection) GetFloat64PropertyFilteredByShardID(key Key, defaultValue f
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, float64CompareEquals)

return val
}
}
Expand All @@ -273,7 +255,7 @@ func (c *Collection) GetFloatPropertyFilteredByNamespace(key Key, defaultValue f
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, float64CompareEquals)

return val
}
}
Expand Down Expand Up @@ -304,7 +286,6 @@ func (c *Collection) GetFloatPropertyFilteredByTaskQueueInfo(key Key, defaultVal
}
}

c.logValue(key, val, defaultValue, float64CompareEquals)
return val
}
}
Expand All @@ -316,7 +297,7 @@ func (c *Collection) GetDurationProperty(key Key, defaultValue time.Duration) Du
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, durationCompareEquals)

return val
}
}
Expand All @@ -328,7 +309,7 @@ func (c *Collection) GetDurationPropertyFilteredByNamespace(key Key, defaultValu
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, durationCompareEquals)

return val
}
}
Expand All @@ -340,7 +321,7 @@ func (c *Collection) GetDurationPropertyFilteredByNamespaceID(key Key, defaultVa
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, durationCompareEquals)

return val
}
}
Expand Down Expand Up @@ -371,7 +352,6 @@ func (c *Collection) GetDurationPropertyFilteredByTaskQueueInfo(key Key, default
}
}

c.logValue(key, val, defaultValue, durationCompareEquals)
return val
}
}
Expand All @@ -387,7 +367,7 @@ func (c *Collection) GetDurationPropertyFilteredByShardID(key Key, defaultValue
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, durationCompareEquals)

return val
}
}
Expand All @@ -399,7 +379,7 @@ func (c *Collection) GetBoolProperty(key Key, defaultValue bool) BoolPropertyFn
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, boolCompareEquals)

return val
}
}
Expand All @@ -411,7 +391,7 @@ func (c *Collection) GetStringProperty(key Key, defaultValue string) StringPrope
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, stringCompareEquals)

return val
}
}
Expand All @@ -423,7 +403,7 @@ func (c *Collection) GetMapProperty(key Key, defaultValue map[string]interface{}
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, reflect.DeepEqual)

return val
}
}
Expand All @@ -435,7 +415,7 @@ func (c *Collection) GetStringPropertyFnWithNamespaceFilter(key Key, defaultValu
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, stringCompareEquals)

return val
}
}
Expand All @@ -447,7 +427,7 @@ func (c *Collection) GetMapPropertyFnWithNamespaceFilter(key Key, defaultValue m
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, reflect.DeepEqual)

return val
}
}
Expand All @@ -459,7 +439,7 @@ func (c *Collection) GetBoolPropertyFnWithNamespaceFilter(key Key, defaultValue
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, boolCompareEquals)

return val
}
}
Expand All @@ -471,7 +451,7 @@ func (c *Collection) GetBoolPropertyFnWithNamespaceIDFilter(key Key, defaultValu
if err != nil {
c.logError(key, err)
}
c.logValue(key, val, defaultValue, boolCompareEquals)

return val
}
}
Expand Down Expand Up @@ -502,7 +482,6 @@ func (c *Collection) GetBoolPropertyFilteredByTaskQueueInfo(key Key, defaultValu
}
}

c.logValue(key, val, defaultValue, boolCompareEquals)
return val
}
}

0 comments on commit 4c212e5

Please sign in to comment.