@@ -20,6 +20,7 @@ import (
20
20
"encoding/json"
21
21
"fmt"
22
22
"io/ioutil"
23
+ "sync/atomic"
23
24
24
25
"go.uber.org/zap"
25
26
@@ -30,16 +31,16 @@ import (
30
31
type strategyStore struct {
31
32
logger * zap.Logger
32
33
33
- defaultStrategy * sampling. SamplingStrategyResponse
34
- serviceStrategies map [ string ] * sampling. SamplingStrategyResponse
34
+ defaultStrategy atomic. Value
35
+ serviceStrategies atomic. Value
35
36
}
36
37
37
38
// NewStrategyStore creates a strategy store that holds static sampling strategies.
38
39
func NewStrategyStore (options Options , logger * zap.Logger ) (ss.StrategyStore , error ) {
39
40
h := & strategyStore {
40
- logger : logger ,
41
- serviceStrategies : make (map [string ]* sampling.SamplingStrategyResponse ),
41
+ logger : logger ,
42
42
}
43
+ h .serviceStrategies .Store (make (map [string ]* sampling.SamplingStrategyResponse ))
43
44
strategies , err := loadStrategies (options .StrategiesFile )
44
45
if err != nil {
45
46
return nil , err
@@ -50,10 +51,25 @@ func NewStrategyStore(options Options, logger *zap.Logger) (ss.StrategyStore, er
50
51
51
52
// GetSamplingStrategy implements StrategyStore#GetSamplingStrategy.
52
53
func (h * strategyStore ) GetSamplingStrategy (serviceName string ) (* sampling.SamplingStrategyResponse , error ) {
53
- if strategy , ok := h .serviceStrategies [serviceName ]; ok {
54
+ serviceStrategies , ok := h .serviceStrategies .Load ().(map [string ]* sampling.SamplingStrategyResponse )
55
+ if ! ok {
56
+ return nil , fmt .Errorf ("wrong type of serviceStrategies" )
57
+ }
58
+ if strategy , ok := serviceStrategies [serviceName ]; ok {
54
59
return strategy , nil
55
60
}
56
- return h .defaultStrategy , nil
61
+ return h .defaultStrategy .Load ().(* sampling.SamplingStrategyResponse ), nil
62
+ }
63
+
64
+ // UpdateSamplingStrategy implements StrategyStore#UpdateSamplingStrategy.
65
+ func (h * strategyStore ) UpdateSamplingStrategy (bytes []byte ) error {
66
+ var strategies strategies
67
+ if err := json .Unmarshal (bytes , & strategies ); err != nil {
68
+ return fmt .Errorf ("failed to unmarshal strategies: %w" , err )
69
+ }
70
+ h .parseStrategies (& strategies )
71
+ h .logger .Info ("Updated strategy:" + string (bytes ))
72
+ return nil
57
73
}
58
74
59
75
// TODO good candidate for a global util function
@@ -73,40 +89,44 @@ func loadStrategies(strategiesFile string) (*strategies, error) {
73
89
}
74
90
75
91
func (h * strategyStore ) parseStrategies (strategies * strategies ) {
76
- h .defaultStrategy = defaultStrategyResponse ()
92
+ defaultStrategy := defaultStrategyResponse ()
93
+ h .defaultStrategy .Store (defaultStrategy )
77
94
if strategies == nil {
78
95
h .logger .Info ("No sampling strategies provided, using defaults" )
79
96
return
80
97
}
81
98
if strategies .DefaultStrategy != nil {
82
- h . defaultStrategy = h .parseServiceStrategies (strategies .DefaultStrategy )
99
+ defaultStrategy = h .parseServiceStrategies (strategies .DefaultStrategy )
83
100
}
84
101
85
102
merge := true
86
- if h . defaultStrategy .OperationSampling == nil ||
87
- h . defaultStrategy .OperationSampling .PerOperationStrategies == nil {
103
+ if defaultStrategy .OperationSampling == nil ||
104
+ defaultStrategy .OperationSampling .PerOperationStrategies == nil {
88
105
merge = false
89
106
}
90
107
108
+ serviceStrategies := make (map [string ]* sampling.SamplingStrategyResponse )
91
109
for _ , s := range strategies .ServiceStrategies {
92
- h . serviceStrategies [s .Service ] = h .parseServiceStrategies (s )
110
+ serviceStrategies [s .Service ] = h .parseServiceStrategies (s )
93
111
94
112
// Merge with the default operation strategies, because only merging with
95
113
// the default strategy has no effect on service strategies (the default strategy
96
114
// is not merged with and only used as a fallback).
97
- opS := h . serviceStrategies [s .Service ].OperationSampling
115
+ opS := serviceStrategies [s .Service ].OperationSampling
98
116
if opS == nil {
99
117
// Service has no per-operation strategies, so just reference the default settings.
100
- h . serviceStrategies [s .Service ].OperationSampling = h . defaultStrategy .OperationSampling
118
+ serviceStrategies [s .Service ].OperationSampling = defaultStrategy .OperationSampling
101
119
continue
102
120
}
103
121
104
122
if merge {
105
123
opS .PerOperationStrategies = mergePerOperationSamplingStrategies (
106
124
opS .PerOperationStrategies ,
107
- h . defaultStrategy .OperationSampling .PerOperationStrategies )
125
+ defaultStrategy .OperationSampling .PerOperationStrategies )
108
126
}
109
127
}
128
+ h .defaultStrategy .Store (defaultStrategy )
129
+ h .serviceStrategies .Store (serviceStrategies )
110
130
}
111
131
112
132
// mergePerOperationStrategies merges two operation strategies a and b, where a takes precedence over b.
0 commit comments