Skip to content

Commit 0202715

Browse files
authored
FFM-9486 Sdd SDK Codes (#130)
1 parent f0fa68c commit 0202715

File tree

9 files changed

+233
-111
lines changed

9 files changed

+233
-111
lines changed

analyticsservice/analytics.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"github.com/harness/ff-golang-server-sdk/sdk_codes"
78
"strconv"
89
"sync"
910
"time"
@@ -72,6 +73,7 @@ func NewAnalyticsService(timeout time.Duration, logger logger.Logger) *Analytics
7273

7374
// Start starts the client and timer to send analytics
7475
func (as *AnalyticsService) Start(ctx context.Context, client *metricsclient.ClientWithResponsesInterface, environmentID string) {
76+
as.logger.Infof("%s Metrics started", sdk_codes.MetricsStarted)
7577
as.metricsClient = client
7678
as.environmentID = environmentID
7779
go as.startTimer(ctx)
@@ -83,6 +85,7 @@ func (as *AnalyticsService) startTimer(ctx context.Context) {
8385
case <-time.After(as.timeout):
8486
as.sendDataAndResetCache(ctx)
8587
case <-ctx.Done():
88+
as.logger.Infof("%s Metrics stopped", sdk_codes.MetricsStopped)
8689
return
8790
}
8891
}
@@ -273,11 +276,11 @@ func (as *AnalyticsService) sendDataAndResetCache(ctx context.Context) {
273276
return
274277
}
275278
if resp.StatusCode() != 200 {
276-
as.logger.Warn("Non 200 response from metrics server: %d", resp.StatusCode())
279+
as.logger.Warnf("%s Non 200 response from metrics server: %d", sdk_codes.MetricsSendFail, resp.StatusCode())
277280
return
278281
}
279282

280-
as.logger.Debug("Metrics sent to server")
283+
as.logger.Debugf("%s Metrics sent to server", sdk_codes.MetricsSendSuccess)
281284
} else {
282285
as.logger.Warn("metrics client is not set")
283286
}

client/client.go

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"github.com/harness/ff-golang-server-sdk/sdk_codes"
89
"log"
910
"math/rand"
1011
"net/http"
@@ -90,7 +91,7 @@ func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) {
9091
}
9192

9293
if sdkKey == "" {
93-
config.Logger.Errorf("Initialization failed: SDK Key cannot be empty. Please provide a valid SDK Key to initialize the client.")
94+
config.Logger.Errorf("%s Initialization failed: SDK Key cannot be empty. Please provide a valid SDK Key to initialize the client.", sdk_codes.InitMissingKey)
9495
return client, EmptySDKKeyError
9596
}
9697

@@ -113,10 +114,13 @@ func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) {
113114

114115
client.start()
115116
if config.waitForInitialized {
117+
config.Logger.Infof("%s The SDK is waiting for initialization to complete'", sdk_codes.InitWaiting)
118+
116119
var initErr error
117120

118121
select {
119122
case <-client.initialized:
123+
config.Logger.Infof("%s The SDK has successfully initialized'", sdk_codes.InitSuccess)
120124
return client, nil
121125
case err := <-client.initializedErr:
122126
initErr = err
@@ -144,6 +148,7 @@ func (c *CfClient) start() {
144148

145149
go func() {
146150
if err := c.initAuthentication(context.Background()); err != nil {
151+
c.config.Logger.Error("%s The SDK has failed to initialize due to an authentication error: %v' ", sdk_codes.InitAuthError, err)
147152
c.initializedErr <- err
148153
}
149154
}()
@@ -240,7 +245,7 @@ func (c *CfClient) streamConnect(ctx context.Context) {
240245
sseClient := sse.NewClient(fmt.Sprintf("%s/stream?cluster=%s", c.config.url, c.clusterIdentifier))
241246

242247
streamErr := func() {
243-
c.config.Logger.Warn("Stream disconnected. Swapping to polling mode")
248+
c.config.Logger.Warnf("%s Stream disconnected. Swapping to polling mode", sdk_codes.StreamDisconnected)
244249
c.mux.RLock()
245250
defer c.mux.RUnlock()
246251
c.streamConnected = false
@@ -276,25 +281,26 @@ func (c *CfClient) initAuthentication(ctx context.Context) error {
276281
for {
277282
err := c.authenticate(ctx)
278283
if err == nil {
284+
c.config.Logger.Infof("%s Authenticated successfully'", sdk_codes.AuthSuccess)
279285
return nil
280286
}
281287

282288
var nonRetryableAuthError NonRetryableAuthError
283289
if errors.As(err, &nonRetryableAuthError) {
284-
c.config.Logger.Error("Authentication failed with a non-retryable error: '%s %s' Default variations will now be served", nonRetryableAuthError.StatusCode, nonRetryableAuthError.Message)
290+
c.config.Logger.Error("%s Authentication failed with a non-retryable error: '%s %s' Default variations will now be served", sdk_codes.AuthFailed, nonRetryableAuthError.StatusCode, nonRetryableAuthError.Message)
285291
return err
286292
}
287293

288294
// -1 is the default maxAuthRetries option and indicates there should be no max attempts
289295
if c.config.maxAuthRetries != -1 && attempts >= c.config.maxAuthRetries {
290-
c.config.Logger.Errorf("Authentication failed with error: '%s'. Exceeded max attempts: '%v'.", err, c.config.maxAuthRetries)
296+
c.config.Logger.Errorf("%s Authentication failed with error: '%s'. Exceeded max attempts: '%v'.", sdk_codes.AuthExceededRetries, err, c.config.maxAuthRetries)
291297
return err
292298
}
293299

294300
jitter := time.Duration(rand.Float64() * float64(currentDelay))
295301
delayWithJitter := currentDelay + jitter
296302

297-
c.config.Logger.Errorf("Authentication failed with error: '%s'. Retrying in %v.", err, delayWithJitter)
303+
c.config.Logger.Errorf("%s Authentication failed with error: '%s'. Retrying in %v.", sdk_codes.AuthAttempt, err, delayWithJitter)
298304
c.config.sleeper.Sleep(delayWithJitter)
299305

300306
currentDelay *= time.Duration(factor)
@@ -414,10 +420,12 @@ func (c *CfClient) makeTicker(interval uint) *time.Ticker {
414420
func (c *CfClient) pullCronJob(ctx context.Context) {
415421
poll := func() {
416422
c.mux.RLock()
423+
c.config.Logger.Infof("%s Polling started, interval: %v", sdk_codes.PollStart, c.config.pullInterval)
417424
if !c.streamConnected {
418425
ok := c.retrieve(ctx)
419426
// we should only try and start the stream after the poll succeeded to make sure we get the latest changes
420427
if ok && c.config.enableStream {
428+
c.config.Logger.Infof("%s Polling Stopped", sdk_codes.PollStop)
421429
// here stream is enabled but not connected, so we attempt to reconnect
422430
c.config.Logger.Info("Attempting to start stream")
423431
c.streamConnect(ctx)
@@ -437,6 +445,8 @@ func (c *CfClient) pullCronJob(ctx context.Context) {
437445
select {
438446
case <-ctx.Done():
439447
pullingTicker.Stop()
448+
c.config.Logger.Infof("%s Polling stopped", sdk_codes.PollStop)
449+
c.config.Logger.Infof("%s Stream stopped", sdk_codes.StreamStop)
440450
return
441451
case <-pullingTicker.C:
442452
poll()
@@ -508,14 +518,18 @@ func (c *CfClient) setAnalyticsServiceClient(ctx context.Context) {
508518
}
509519

510520
// BoolVariation returns the value of a boolean feature flag for a given target.
511-
//
512521
// Returns defaultValue if there is an error or if the flag doesn't exist
513522
func (c *CfClient) BoolVariation(key string, target *evaluation.Target, defaultValue bool) (bool, error) {
514523
if !c.initializedBool {
515-
c.config.Logger.Info("Error when calling BoolVariation and returning default variation: 'Client is not initialized'")
524+
c.config.Logger.Infof("%s Error while evaluating boolean flag and returning default variation: 'Client is not initialized'", sdk_codes.EvaluationFailed)
516525
return defaultValue, fmt.Errorf("%w: Client is not initialized", DefaultVariationReturnedError)
517526
}
518-
value := c.evaluator.BoolVariation(key, target, defaultValue)
527+
value, err := c.evaluator.BoolVariation(key, target, defaultValue)
528+
if err != nil {
529+
c.config.Logger.Infof("%s Error while evaluating boolean flag and returning default variation '%s', err: %v", sdk_codes.EvaluationFailed, key, err)
530+
return value, fmt.Errorf("%w: `%v`", DefaultVariationReturnedError, err)
531+
}
532+
c.config.Logger.Debugf("%s Evaluated boolean flag successfully: '%s'", sdk_codes.EvaluationSuccess, key)
519533
return value, nil
520534
}
521535

@@ -524,10 +538,15 @@ func (c *CfClient) BoolVariation(key string, target *evaluation.Target, defaultV
524538
// Returns defaultValue if there is an error or if the flag doesn't exist
525539
func (c *CfClient) StringVariation(key string, target *evaluation.Target, defaultValue string) (string, error) {
526540
if !c.initializedBool {
527-
c.config.Logger.Info("Error when calling StringVariation and returning default variation: 'Client is not initialized'")
541+
c.config.Logger.Infof("%s Error while evaluating string flag and returning default variation: 'Client is not initialized'", sdk_codes.EvaluationFailed)
528542
return defaultValue, fmt.Errorf("%w: Client is not initialized", DefaultVariationReturnedError)
529543
}
530-
value := c.evaluator.StringVariation(key, target, defaultValue)
544+
value, err := c.evaluator.StringVariation(key, target, defaultValue)
545+
if err != nil {
546+
c.config.Logger.Infof("%s Error while evaluating string flag '%s', err: %v", sdk_codes.EvaluationFailed, key, err)
547+
return value, fmt.Errorf("%w: `%v`", DefaultVariationReturnedError, err)
548+
}
549+
c.config.Logger.Debugf("%s Evaluated string flag successfully: '%s'", sdk_codes.EvaluationSuccess, key)
531550
return value, nil
532551
}
533552

@@ -536,10 +555,15 @@ func (c *CfClient) StringVariation(key string, target *evaluation.Target, defaul
536555
// Returns defaultValue if there is an error or if the flag doesn't exist
537556
func (c *CfClient) IntVariation(key string, target *evaluation.Target, defaultValue int64) (int64, error) {
538557
if !c.initializedBool {
539-
c.config.Logger.Info("Error when calling IntVariation and returning default variation: 'Client is not initialized'")
558+
c.config.Logger.Infof("%s Error while evaluating int flag and returning default variation: 'Client is not initialized'", sdk_codes.EvaluationFailed)
540559
return defaultValue, fmt.Errorf("%w: Client is not initialized", DefaultVariationReturnedError)
541560
}
542-
value := c.evaluator.IntVariation(key, target, int(defaultValue))
561+
value, err := c.evaluator.IntVariation(key, target, int(defaultValue))
562+
if err != nil {
563+
c.config.Logger.Infof("%s Error while evaluating int flag '%s', err: %v", sdk_codes.EvaluationFailed, key, err)
564+
return int64(value), fmt.Errorf("%w: `%v`", DefaultVariationReturnedError, err)
565+
}
566+
c.config.Logger.Debugf("%s Evaluated int flag successfully: '%s'", sdk_codes.EvaluationSuccess, key)
543567
return int64(value), nil
544568
}
545569

@@ -548,10 +572,15 @@ func (c *CfClient) IntVariation(key string, target *evaluation.Target, defaultVa
548572
// Returns defaultValue if there is an error or if the flag doesn't exist
549573
func (c *CfClient) NumberVariation(key string, target *evaluation.Target, defaultValue float64) (float64, error) {
550574
if !c.initializedBool {
551-
c.config.Logger.Info("Error when calling NumberVariation and returning default variation: 'Client is not initialized'")
575+
c.config.Logger.Infof("%s Error while number number flag and returning default variation: 'Client is not initialized'", sdk_codes.EvaluationFailed)
552576
return defaultValue, fmt.Errorf("%w: Client is not initialized", DefaultVariationReturnedError)
553577
}
554-
value := c.evaluator.NumberVariation(key, target, defaultValue)
578+
value, err := c.evaluator.NumberVariation(key, target, defaultValue)
579+
if err != nil {
580+
c.config.Logger.Infof("%s Error while evaluating number flag '%s', err: %v", sdk_codes.EvaluationFailed, key, err)
581+
return value, fmt.Errorf("%w: `%v`", DefaultVariationReturnedError, err)
582+
}
583+
c.config.Logger.Debugf("%s Evaluated number flag successfully: '%s'", sdk_codes.EvaluationSuccess, key)
555584
return value, nil
556585
}
557586

@@ -561,10 +590,15 @@ func (c *CfClient) NumberVariation(key string, target *evaluation.Target, defaul
561590
// Returns defaultValue if there is an error or if the flag doesn't exist
562591
func (c *CfClient) JSONVariation(key string, target *evaluation.Target, defaultValue types.JSON) (types.JSON, error) {
563592
if !c.initializedBool {
564-
c.config.Logger.Info("Error when calling JSONVariation and returning default variation: 'Client is not initialized'")
593+
c.config.Logger.Infof("%s Error while evaluating json flag and returning default variation: 'Client is not initialized'", sdk_codes.EvaluationFailed)
565594
return defaultValue, fmt.Errorf("%w: Client is not initialized", DefaultVariationReturnedError)
566595
}
567-
value := c.evaluator.JSONVariation(key, target, defaultValue)
596+
value, err := c.evaluator.JSONVariation(key, target, defaultValue)
597+
if err != nil {
598+
c.config.Logger.Infof("%s Error while evaluating json flag '%s', err: %v", sdk_codes.EvaluationFailed, key, err)
599+
return value, fmt.Errorf("%w: `%v`", DefaultVariationReturnedError, err)
600+
}
601+
c.config.Logger.Debugf("%s Evaluated json flag successfully: '%s'", sdk_codes.EvaluationSuccess, key)
568602
return value, nil
569603
}
570604

@@ -577,13 +611,21 @@ func (c *CfClient) Close() error {
577611
if c.stopped.get() {
578612
return errors.New("client already closed")
579613
}
614+
c.config.Logger.Infof("%s Closing SDK", sdk_codes.CloseStarted)
580615
close(c.stop)
581616

582617
c.stopped.set(true)
618+
619+
// This flag is used by `IsInitialized` so set to true.
620+
c.initializedBoolLock.Lock()
621+
c.initializedBool = false
622+
c.initializedBoolLock.Unlock()
623+
c.config.Logger.Infof("%s SDK Closed successfully", sdk_codes.CloseSuccess)
624+
583625
return nil
584626
}
585627

586-
// Environment returns environment based on authenticated SDK key
628+
// Environment returns environment based on authenticated SDK flagIdentifier
587629
func (c *CfClient) Environment() string {
588630
return c.environmentID
589631
}

0 commit comments

Comments
 (0)