Skip to content

Commit b9e9060

Browse files
added profiling ability
1 parent d3101c2 commit b9e9060

File tree

3 files changed

+141
-4
lines changed

3 files changed

+141
-4
lines changed

examples/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Optimizely Go SDK Examples
2+
3+
4+
### Content
5+
There are 2 functions:
6+
7+
* `examples()`
8+
* `stressTest()`
9+
10+
`examples()` shows how to instantiate and execute various versions of Optimizely Clients
11+
12+
`stressTest()` is used to stress test our optimizely app and run cpu and memory profiling
13+
14+
15+
### Profiling
16+
Prerequisite: `go get github.com/pkg/profile`
17+
18+
* CPU profile. Execute: `go build -ldflags "-X main.RunCPUProfile=true" main.go && ./main`. It will create cpu.pprof file in your current directory. Then run: `go tool pprof -http=:8080 cpu.pprof` and profile cpu usage using web browser.
19+
* Memory profile. Execute: `go build -ldflags "-X main.RunMemProfile=true" main.go && ./main`. It will create mem.pprof file in your current directory. Then run: `go tool pprof -http=:8080 mem.pprof` and profile memory using browser.

examples/main.go

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,113 @@
1+
// to run the CPU profiling: go build -ldflags "-X main.RunCPUProfile=true" main.go && ./main
2+
// to run the Mem profiling: go build -ldflags "-X main.RunMemProfile=true" main.go && ./main
3+
14
package main
25

36
import (
47
"context"
8+
"encoding/json"
59
"fmt"
10+
"io/ioutil"
11+
"log"
12+
"os"
13+
"path"
614
"time"
715

816
"github.com/optimizely/go-sdk/optimizely/client"
17+
"github.com/optimizely/go-sdk/optimizely/decision"
918
"github.com/optimizely/go-sdk/optimizely/entities"
1019
"github.com/optimizely/go-sdk/optimizely/logging"
20+
"github.com/optimizely/go-sdk/optimizely/notification"
21+
22+
"github.com/pkg/profile"
1123
)
1224

13-
func main() {
25+
// stressTest has everything that test app has. it is used to run profile
26+
func stressTest() {
27+
/*
28+
For the test app, the biggest json file is used with 100 entities.
29+
DATAFILES_DIR has to be set to point to the path where 100_entities.json is located.
30+
*/
31+
type isFeatureEnabledRequestParams struct {
32+
FeatureKey string `json:"feature_flag_key"`
33+
UserID string `json:"user_id"`
34+
Attributes map[string]interface{} `json:"attributes"`
35+
}
36+
37+
type Context struct {
38+
CustomEventDispatcher string `json:"custom_event_dispatcher"`
39+
RequestID string `json:"request_id"`
40+
UserProfileService string `json:"user_profile_service"`
41+
Datafile string `json:"datafile"`
42+
DispatchedEvents []map[string]interface{} `json:"dispatched_events"`
43+
}
44+
45+
strBytes := []byte(` { "context": {
46+
"datafile": "100_entities.json",
47+
"custom_event_dispatcher": "ProxyEventDispatcher",
48+
"request_id": "4e3e37e3-c7ae-4cb6-bbb5-f6ef93c84d43",
49+
"user_profile_service": "NoOpService",
50+
"user_profiles": [],
51+
"with_listener": []
52+
},
53+
"user_id": "test_user_1",
54+
"feature_flag_key": "feature_5",
55+
"attributes": {
56+
"attr_5": "testvalue"
57+
}
58+
}`)
59+
60+
var params isFeatureEnabledRequestParams
61+
err := json.Unmarshal(strBytes, &params)
62+
if err != nil {
63+
log.Fatal(err)
64+
}
65+
66+
var requestBodyMap map[string]*json.RawMessage
67+
68+
err = json.Unmarshal(strBytes, &requestBodyMap)
69+
if err != nil {
70+
log.Fatal(err)
71+
}
72+
73+
var fscCtx Context
74+
err = json.Unmarshal(*requestBodyMap["context"], &fscCtx)
75+
if err != nil {
76+
log.Fatal(err)
77+
}
78+
79+
var datafileDir = path.Join(os.Getenv("DATAFILES_DIR"), fscCtx.Datafile)
80+
81+
datafile, err := ioutil.ReadFile(datafileDir)
82+
if err != nil {
83+
log.Fatal(err)
84+
}
85+
86+
optlyClient := &client.OptimizelyFactory{
87+
Datafile: datafile,
88+
}
89+
90+
user := entities.UserContext{
91+
ID: params.UserID,
92+
Attributes: params.Attributes,
93+
}
94+
95+
// Creates a default, canceleable context
96+
notificationCenter := notification.NewNotificationCenter()
97+
decisionService := decision.NewCompositeService(notificationCenter)
98+
99+
clientOptions := client.Options{
100+
DecisionService: decisionService,
101+
}
102+
clientApp, err := optlyClient.ClientWithOptions(clientOptions)
103+
if err != nil {
104+
log.Fatal(err)
105+
}
106+
107+
clientApp.IsFeatureEnabled(params.FeatureKey, user)
108+
}
109+
110+
func examples() {
14111
logging.SetLogLevel(logging.LogLevelDebug)
15112
optimizelyFactory := &client.OptimizelyFactory{
16113
SDKKey: "4SLpaJA1r1pgE6T2CoMs9q",
@@ -80,3 +177,26 @@ func main() {
80177
enabled, _ = app.IsFeatureEnabled("mutext_feat", user)
81178
fmt.Printf("Is feature enabled? %v\n", enabled)
82179
}
180+
181+
var RunMemProfile = "false"
182+
var RunCPUProfile = "false"
183+
184+
func main() {
185+
186+
if RunMemProfile == "true" || RunCPUProfile == "true" {
187+
188+
const RUN_NUMBER = 6
189+
if RunMemProfile == "true" {
190+
defer profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.MemProfileRate(1)).Stop()
191+
} else if RunCPUProfile == "true" {
192+
defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
193+
}
194+
195+
for i := 0; i < RUN_NUMBER; i++ {
196+
stressTest()
197+
}
198+
} else {
199+
examples()
200+
}
201+
202+
}

optimizely/client/factory.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ package client
2020
import (
2121
"context"
2222
"errors"
23-
"fmt"
2423
"time"
2524

2625
"github.com/optimizely/go-sdk/optimizely/event"
@@ -53,8 +52,7 @@ func (f OptimizelyFactory) StaticClient() (*OptimizelyClient, error) {
5352
var configManager optimizely.ProjectConfigManager
5453

5554
if f.SDKKey != "" {
56-
url := fmt.Sprintf(config.DatafileURLTemplate, f.SDKKey)
57-
staticConfigManager, err := config.NewStaticProjectConfigManagerFromURL(url)
55+
staticConfigManager, err := config.NewStaticProjectConfigManagerFromURL(f.SDKKey)
5856

5957
if err != nil {
6058
return nil, err

0 commit comments

Comments
 (0)