@@ -32,18 +32,24 @@ type OldFlagEvaluationService struct {
3232 metrics telemetry.IMetricsRecorder
3333 eventingConfiguration IEvents
3434 flagEvalTracer trace.Tracer
35+ contextValues map [string ]any
3536}
3637
3738// NewOldFlagEvaluationService creates a OldFlagEvaluationService with provided parameters
38- func NewOldFlagEvaluationService (log * logger.Logger ,
39- eval evaluator.IEvaluator , eventingCfg IEvents , metricsRecorder telemetry.IMetricsRecorder ,
39+ func NewOldFlagEvaluationService (
40+ log * logger.Logger ,
41+ eval evaluator.IEvaluator ,
42+ eventingCfg IEvents ,
43+ metricsRecorder telemetry.IMetricsRecorder ,
44+ contextValues map [string ]any ,
4045) * OldFlagEvaluationService {
4146 svc := & OldFlagEvaluationService {
4247 logger : log ,
4348 eval : eval ,
4449 metrics : & telemetry.NoopMetricsRecorder {},
4550 eventingConfiguration : eventingCfg ,
4651 flagEvalTracer : otel .Tracer ("flagEvaluationService" ),
52+ contextValues : contextValues ,
4753 }
4854
4955 if metricsRecorder != nil {
@@ -65,12 +71,8 @@ func (s *OldFlagEvaluationService) ResolveAll(
6571 res := & schemaV1.ResolveAllResponse {
6672 Flags : make (map [string ]* schemaV1.AnyFlag ),
6773 }
68- evalCtx := map [string ]any {}
69- if e := req .Msg .GetContext (); e != nil {
70- evalCtx = e .AsMap ()
71- }
7274
73- values , err := s .eval .ResolveAllValues (sCtx , reqID , evalCtx )
75+ values , err := s .eval .ResolveAllValues (sCtx , reqID , mergeContexts ( req . Msg . GetContext (). AsMap (), s . contextValues ) )
7476 if err != nil {
7577 s .logger .WarnWithID (reqID , fmt .Sprintf ("error resolving all flags: %v" , err ))
7678 return nil , fmt .Errorf ("error resolving flags. Tracking ID: %s" , reqID )
@@ -172,6 +174,7 @@ func (s *OldFlagEvaluationService) ResolveBoolean(
172174 sCtx , span := s .flagEvalTracer .Start (ctx , "resolveBoolean" , trace .WithSpanKind (trace .SpanKindServer ))
173175 defer span .End ()
174176 res := connect .NewResponse (& schemaV1.ResolveBooleanResponse {})
177+
175178 err := resolve [bool ](
176179 sCtx ,
177180 s .logger ,
@@ -180,6 +183,7 @@ func (s *OldFlagEvaluationService) ResolveBoolean(
180183 req .Msg .GetContext (),
181184 & booleanResponse {schemaV1Resp : res },
182185 s .metrics ,
186+ s .contextValues ,
183187 )
184188 if err != nil {
185189 span .RecordError (err )
@@ -206,6 +210,7 @@ func (s *OldFlagEvaluationService) ResolveString(
206210 req .Msg .GetContext (),
207211 & stringResponse {schemaV1Resp : res },
208212 s .metrics ,
213+ s .contextValues ,
209214 )
210215 if err != nil {
211216 span .RecordError (err )
@@ -232,6 +237,7 @@ func (s *OldFlagEvaluationService) ResolveInt(
232237 req .Msg .GetContext (),
233238 & intResponse {schemaV1Resp : res },
234239 s .metrics ,
240+ s .contextValues ,
235241 )
236242 if err != nil {
237243 span .RecordError (err )
@@ -258,6 +264,7 @@ func (s *OldFlagEvaluationService) ResolveFloat(
258264 req .Msg .GetContext (),
259265 & floatResponse {schemaV1Resp : res },
260266 s .metrics ,
267+ s .contextValues ,
261268 )
262269 if err != nil {
263270 span .RecordError (err )
@@ -284,6 +291,7 @@ func (s *OldFlagEvaluationService) ResolveObject(
284291 req .Msg .GetContext (),
285292 & objectResponse {schemaV1Resp : res },
286293 s .metrics ,
294+ s .contextValues ,
287295 )
288296 if err != nil {
289297 span .RecordError (err )
@@ -293,21 +301,36 @@ func (s *OldFlagEvaluationService) ResolveObject(
293301 return res , err
294302}
295303
304+ // mergeContexts combines values from the request context with the values from the config --context-values flag.
305+ // Request context values have a higher priority.
306+ func mergeContexts (reqCtx , configFlagsCtx map [string ]any ) map [string ]any {
307+ merged := make (map [string ]any )
308+ for k , v := range reqCtx {
309+ merged [k ] = v
310+ }
311+ for k , v := range configFlagsCtx {
312+ merged [k ] = v
313+ }
314+ return merged
315+ }
316+
296317// resolve is a generic flag resolver
297318func resolve [T constraints ](ctx context.Context , logger * logger.Logger , resolver resolverSignature [T ], flagKey string ,
298319 evaluationContext * structpb.Struct , resp response [T ], metrics telemetry.IMetricsRecorder ,
320+ configContextValues map [string ]any ,
299321) error {
300322 reqID := xid .New ().String ()
301323 defer logger .ClearFields (reqID )
302324
325+ mergedContext := mergeContexts (evaluationContext .AsMap (), configContextValues )
303326 logger .WriteFields (
304327 reqID ,
305328 zap .String ("flag-key" , flagKey ),
306- zap .Strings ("context-keys" , formatContextKeys (evaluationContext )),
329+ zap .Strings ("context-keys" , formatContextKeys (mergedContext )),
307330 )
308331
309332 var evalErrFormatted error
310- result , variant , reason , metadata , evalErr := resolver (ctx , reqID , flagKey , evaluationContext . AsMap () )
333+ result , variant , reason , metadata , evalErr := resolver (ctx , reqID , flagKey , mergedContext )
311334 if evalErr != nil {
312335 logger .WarnWithID (reqID , fmt .Sprintf ("returning error response, reason: %v" , evalErr ))
313336 reason = model .ErrorReason
@@ -329,9 +352,9 @@ func resolve[T constraints](ctx context.Context, logger *logger.Logger, resolver
329352 return evalErrFormatted
330353}
331354
332- func formatContextKeys (context * structpb. Struct ) []string {
355+ func formatContextKeys (context map [ string ] any ) []string {
333356 res := []string {}
334- for k := range context . AsMap () {
357+ for k := range context {
335358 res = append (res , k )
336359 }
337360 return res
0 commit comments