Skip to content

Commit 3787b9c

Browse files
authored
Docs readme sync 3 (#251)
Docs readme sync 3
1 parent 449c3d5 commit 3787b9c

16 files changed

+747
-0
lines changed

.travis.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ stages:
2121
- 'Build, Upload and Publish (draft)'
2222
- 'Test github release assets'
2323
- 'Publish (real)'
24+
- 'Readme-sync'
2425

2526
jobs:
2627

@@ -217,6 +218,55 @@ jobs:
217218
# how to use hub: https://hub.github.com/hub.1.html
218219
- hub release edit --draft=false -m "" ${TRAVIS_TAG}
219220

221+
- stage: 'Readme-sync'
222+
before_script: skip
223+
cache: false
224+
# translation: if we're merging into a master branch...
225+
if: type = push AND branch = master
226+
227+
language: node_js
228+
install:
229+
230+
231+
# make dir $HOME/readme-sync2 & clone readme-sync2 repo to it; install dependencies
232+
233+
- mkdir $HOME/readme-sync2 && pushd $HOME/readme-sync2 && git init && git pull https://[email protected]/optimizely/readme-sync2.git && popd
234+
- source ~/.nvm/nvm.sh && cd $HOME/readme-sync2 && nvm install && npm install
235+
236+
script:
237+
# we need to be in $TRAVIS_BUILD_DIR in order to run the following git diff properly
238+
- cd $TRAVIS_BUILD_DIR
239+
240+
#print which docs changed in this Pull Request (and which therefore we expect to be updated by readme-sync-2 tool):
241+
- CHANGED_DOCS_FILES=($(git diff --name-only $TRAVIS_COMMIT_RANGE -- docs/readme-sync))
242+
- echo $CHANGED_DOCS_FILES
243+
244+
#only if changes were made in the docs/readme-sync repo, trigger this readme-sync stage and sync the docs
245+
- git diff --quiet $TRAVIS_COMMIT_RANGE -- docs/readme-sync || ( cd $HOME/readme-sync2 && npx ts-node sync/index.ts --apiKey $README_SYNC_API_KEY --version 3.1 --docs $TRAVIS_BUILD_DIR/docs/readme-sync/)
246+
247+
#########################################################################################
248+
# directories/scripts for full SDK-reference-guides, to be implemented after agent docs sync
249+
#########################################################################################
250+
## this preps the input directory for readme-sync script
251+
#- mkdir -p $HOME/readme-sync2/docs/readme-sync/sdk-reference-guides
252+
## ${TRAVIS_REPO_SLUG#optimizely/} translates to go-sdk docs/readme-sync/sdk-reference-guides/go-sdk
253+
#- ln -s $TRAVIS_BUILD_DIR/docs/readme-sync/sdk-reference-guides/${TRAVIS_REPO_SLUG#optimizely/} $HOME/readme-sync2/docs/readme-sync/sdk-reference-guides/${TRAVIS_REPO_SLUG#optimizely/}
254+
255+
## now we need to get all the other *-sdk repos too
256+
##
257+
## first we list all possible sdks and inside the for loop, remove the one we are updating
258+
#- export ALL_SDK_REPOS="android-sdk csharp-sdk go-sdk java-sdk javascript-sdk objective-c-sdk python-sdk react-sdk ruby-sdk swift-sdk"
259+
#- mkdir $HOME/sdks && pushd $HOME/sdks && for i in ${ALL_SDK_REPOS//${TRAVIS_REPO_SLUG#optimizely/}}; do git clone https://github.com/optimizely/$i; ( [ -d "$HOME/sdks/$i/docs/readme-sync/sdk-reference-guides/$i" ] && ln -s $HOME/sdks/$i/docs/readme-sync/sdk-reference-guides/$i $HOME/readme-sync2/docs/readme-sync/sdk-reference-guides/$i ) || true; done && popd
260+
## check our work
261+
#- ls -al $HOME/sdks
262+
#- ls -al $HOME/readme-sync2/docs/readme-sync/sdk-reference-guides
263+
#script:
264+
## we need to be in $TRAVIS_BUILD_DIR in order to run the following git diff properly
265+
#- cd $TRAVIS_BUILD_DIR
266+
#- git diff --quiet $TRAVIS_COMMIT_RANGE -- docs/readme-sync || ( cd $HOME/readme-sync2 && npx ts-node sync/index.ts --apiKey $README_SYNC_API_KEY --version 4.0 --docs docs/readme-sync/ )
267+
268+
269+
220270
before_script:
221271
# https://github.com/travis-ci/gimme
222272
- eval "$(gimme)"
682 KB
Loading
885 KB
Loading

docs/images/agent-single-service.png

818 KB
Loading
121 KB
Loading
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
title: "Optimizely Agent"
3+
excerpt: ""
4+
slug: "optimizely-agent"
5+
hidden: false
6+
metadata:
7+
title: "Optimizely Agent microservice - Optimizely Full Stack"
8+
createdAt: "2020-02-21T20:35:58.387Z"
9+
updatedAt: "2020-07-14T20:51:52.458Z"
10+
---
11+
Optimizely Agent is a standalone, open-source, and highly available microservice that provides major benefits over using Optimizely SDKs in certain use cases. The Agent [REST API](https://library.optimizely.com/docs/api/agent/v1/index.html) offers consolidated and simplified endpoints for accessing all the functionality of Optimizely Full Stack SDKs.
12+
13+
A typical production installation of Optimizely Agent is to run two or more services behind a load balancer or proxy. The service itself can be run via a Docker container or installed from source. See [Setup Optimizely Agent](doc:setup-optimizely-agent) for instructions on how to run Optimizely Agent.
14+
15+
### Example Implementation
16+
![example implementation](https://github.com/raw/optimizely/agent/master/docs/images/agent-example-implementation.png)
17+
# Should I Use Optimizely Agent?
18+
19+
Here are some of the top reasons to consider using Optimizely Agent:
20+
21+
## 1. Service Oriented Architecture (SOA)
22+
If you already separate some of your logic into services that might need to access the Optimizely decision APIs, we recommend using Optimizely Agent.
23+
24+
The images below compare implementation styles in a service-oriented architecture, first *without* using Optimizely Agent, which shows six SDK embedded instances:
25+
26+
!["A diagram showing the use of SDKs installed on each service in a service oriented architecture \n(Click to Enlarge)"](https://github.com/raw/optimizely/agent/master/docs/images/agent-service-oriented-architecture.png)
27+
28+
Now *with* Agent, instead of installing the SDK six times, you create just one Optimizely instance: an HTTP API that every service can access as needed.
29+
30+
!["A diagram showing the use of Optimizely Agent in a single service \n(Click to Enlarge)"](https://github.com/raw/optimizely/agent/master/docs/images/agent-single-service.png)
31+
32+
## 2. Standardize Access Across Teams
33+
If you want to deploy Optimizely Full Stack once, then roll out the single implementation across a large number of teams, we recommend using Optimizely Agent.
34+
35+
By standardizing your teams' access to the Optimizely service, you can better enforce processes and implement governance around feature management and experimentation as a practice.
36+
37+
!["A diagram showing the central and standardized access to the Optimizely Agent service across an arbitrary number of teams.\n(Click to Enlarge)"](https://github.com/raw/optimizely/agent/master/docs/images/agent-standardized-access.png)
38+
39+
## 3. Networking Centralization
40+
You don’t want many SDK instances connecting to Optimizely's cloud service from every node in your application. Optimizely Agent centralizes your network connection. Only one cluster of agent instances connects to Optimizely for tasks like update [datafiles](doc:get-the-datafile) and dispatch [events](doc:track-events).
41+
42+
## 4. Languages
43+
You’re using a language that isn’t supported by a native SDK (i.e. Elixir, Scala, Perl). While its possible to create your own service using an Optimizely SDK of your choice, you could also customize the open-source Optimizely Agent to your needs without building the service layer on your own.
44+
45+
46+
# Reasons to *not* use Optimizely Agent
47+
If your use case wouldn't benefit greatly from Optimizely Agent, you should consider the below reasons to *not* use Optimizely Agent and review Optimizely's many [open-source SDKs](doc:sdk-reference-guides) instead.
48+
49+
## 1. Latency
50+
If time to provide bucketing decisions is a primary concern for you, you may want to use an embedded Full Stack SDK rather than Optimizely Agent.
51+
52+
53+
| Implementation Option | Decision Latency |
54+
|-----------------------|------------------|
55+
| Embedded SDK | microseconds |
56+
| Optimizely Agent | milliseconds |
57+
58+
## 2. Monolith
59+
If your app is constructed as a monolith, embedded SDKs might be easier to install and might be a more natural fit for your application and development practices.
60+
61+
## 3. Velocity
62+
If you’re looking for the fastest way to get a single team up and running with deploying feature management and experimentation, embedding an SDK is the best option for you at first. You can always start using Optimizely Agent later, and it can even be used alongside Optimizely Full Stack SDKs running in another part of your stack.
63+
64+
# Best Practices
65+
While every implementation is different, you can review this section of best practices for tips on these commonly discussed topics.
66+
67+
68+
## How many Agent instances should I deploy?
69+
Agent can scale to large decision / event tracking volumes with relatively low CPU / memory specs. For example, at Optimizely, we scaled our deployment to 740 clients with a cluster of 12 agent instances, which in total use 6 vCPUs and 12GB RAM. You will likely need to focus more on network bandwidth than compute power.
70+
71+
## Using a load balancer
72+
Any standard load balancer should let you route traffic across your agent cluster. At Optimizely, we used an AWS Elastic Load Balancer (ELB) for our internal deployment. This allows us to transparently scale our agent cluster as internal demands increase.
73+
74+
## Synchronizing datafiles across Agent instances
75+
Agent offers eventual rather than strong consistency across datafiles.
76+
In detail, today, each agent instance maintains a dedicated, separate cache. Each agent instance persists an SDK instance for each SDK key your team uses. Agent instances automatically keep datafiles up to date for each SDK key instance so that you will have eventual consistency across the cluster. The rate of the datafile update can be [set as the configuration](doc:configure-optimizely-agent) value ```OPTIMIZELY_CLIENT_POLLINGINTERVAL``` (the default is 1 minute).
77+
Because SDKs are generally stateless today, they shouldn’t need to share data. We plan to add a common backing data store, so we invite you to share your feedback.
78+
If you require strong consistency across datafiles, then we recommend an active / passive deployment where all requests are made to a single vertically scaled host, with a passive, standby cluster available for high availability.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
---
2+
title: "Set up Optimizely Agent"
3+
excerpt: ""
4+
slug: "setup-optimizely-agent"
5+
hidden: false
6+
metadata:
7+
title: "Getting started with Agent - Optimizely Full Stack"
8+
createdAt: "2020-02-21T17:44:27.363Z"
9+
updatedAt: "2020-03-31T23:54:17.841Z"
10+
---
11+
## Running Agent from source (Linux / OSX)
12+
13+
To develop and compile Optimizely Agent from source:
14+
15+
1. Install [Golang](https://golang.org/dl/) version 1.13+ .
16+
2. Clone the [Optimizely Agent repo](https://github.com/optimizely/agent).
17+
3. From the repo directory, open a terminal and start Optimizely Agent:
18+
19+
```bash
20+
make setup
21+
```
22+
Then
23+
```bash
24+
make run
25+
```
26+
27+
This starts the Optimizely Agent with the default configuration in the foreground.
28+
29+
## Running Agent from source (Windows)
30+
31+
You can use a [helper script](https://github.com/optimizely/agent/blob/master/scripts/build.ps1) to install prerequisites (Golang, Git) and compile agent in a Windows environment. Take these steps:
32+
33+
1. Clone the [Optimizely Agent repo](https://github.com/optimizely/agent)
34+
2. From the repo directory, open a Powershell terminal and run
35+
36+
```bash
37+
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
38+
39+
.\scripts\build.ps1
40+
41+
.\bin\optimizely.exe
42+
```
43+
44+
## Running Agent via Docker
45+
46+
If you have Docker installed, you can start Optimizely Agent as a container. Take these steps:
47+
48+
1. Pull the Docker image:
49+
50+
```bash
51+
docker pull optimizely/agent
52+
```
53+
By default this will pull the "latest" tag. You can also specify a specific version of Agent by providing the version as a tag to the docker command:
54+
55+
```bash
56+
docker pull optimizely/agent:X.Y.Z
57+
```
58+
59+
2. Run the docker container with:
60+
61+
```bash
62+
docker run -p 8080:8080 optimizely/agent
63+
```
64+
This will start Agent in the foreground and expose the container API port 8080 to the host.
65+
66+
3. (Optional) You can alter the configuration by passing in environment variables to the preceding command, without having to create a config.yaml file. See [configure optimizely agent](doc:configure-optimizely-agent) for more options.
67+
68+
Versioning:
69+
When a new version is released, 2 images are pushed to dockerhub. They are distinguished by their tags:
70+
- :latest (same as :X.Y.Z)
71+
- :alpine (same as :X.Y.Z-alpine)
72+
73+
The difference between latest and alpine is that latest is built `FROM scratch` while alpine is `FROM alpine`.
74+
- [latest Dockerfile](https://github.com/optimizely/agent/blob/master/scripts/dockerfiles/Dockerfile.static)
75+
- [alpine Dockerfile](https://github.com/optimizely/agent/blob/master/scripts/dockerfiles/Dockerfile.alpine)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
title: "Evaluate REST APIs"
3+
excerpt: ""
4+
slug: "evaluate-rest-apis"
5+
hidden: false
6+
metadata:
7+
title: "Evaluate REST APIs - Optimizely Full Stack"
8+
createdAt: "2020-02-21T17:44:53.019Z"
9+
updatedAt: "2020-04-13T23:02:34.056Z"
10+
---
11+
Below is an example demonstrating the APIs capabilities. For brevity, we've chosen to illustrate the API usage with Python. Note that the API documentation is defined via an OpenAPI (Swagger) spec and can be viewed [here](https://library.optimizely.com/docs/api/agent/v1/index.htm).
12+
13+
## Start an http session
14+
Each request made into Optimizely Agent is in the context of an Optimizely SDK Key. SDK Keys map API requests to a specific Optimizely Project and Environment. We can setup a global request header by using the `requests.Session` object.
15+
16+
17+
```python
18+
import requests
19+
20+
s = requests.Session()
21+
s.headers.update({'X-Optimizely-SDK-Key': 'YOUR-SDK-KEY'})
22+
```
23+
The following examples will assume this session is being maintained.
24+
25+
## Get current environment configuration
26+
The `/v1/config` endpoint returns a manifest of the current working environment.
27+
28+
```python
29+
resp = s.get('http://localhost:8080/v1/config')
30+
env = resp.json()
31+
32+
for key in env['featuresMap']:
33+
print(key)
34+
```
35+
36+
## Activate Feature
37+
The `/v1/activate?featureKey={key}` endpoint activates the feature for a given user. In Optimizely, activation is in the context of a given user to make the relative bucketing decision. In this case we'll provide a `userId` via the request body. The `userId` will be used to determine how the feature will be evaluated. Features can either be part of a Feature Test in which variations of feature variables are being measured against one another or a feature rollout, which progressively make the feature available to the selected audience.
38+
39+
From an API standpoint the presence of a Feature Test or Rollout is abstracted away from the response and only the resulting variation or enabled feature is returned.
40+
41+
42+
```python
43+
# single feature activate
44+
params = { "featureKey": "my-feature" }
45+
payload = { "userId": "test-user" }
46+
resp = s.post(url = 'http://localhost:8080/v1/activate', params=params, json=payload)
47+
48+
print(resp.json())
49+
50+
51+
# multiple (bulk) feature activate
52+
params = {
53+
"featureKey": [key for key in env['featuresMap']],
54+
"experimentKey": [key for key in env['experimentsMap']]
55+
}
56+
resp2 = s.post(url = 'http://localhost:8080/v1/activate', params=params, json=payload)
57+
print(json.dumps(resp.json(), indent=4, sort_keys=True))
58+
```
59+
The activate API is a POST to signal to the caller that there are side-effects. Namely, activation results in a "decision" event sent to Optimizely analytics for the purpose of analyzing Feature Test results. A "decision" will NOT be sent if the feature is simply part of a rollout.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
title: "Admin API"
3+
excerpt: ""
4+
slug: "admin-api"
5+
hidden: false
6+
metadata:
7+
title: "Admin APIs - Optimizely Full Stack"
8+
createdAt: "2020-02-21T17:44:28.054Z"
9+
updatedAt: "2020-02-21T23:09:19.274Z"
10+
---
11+
The Admin API provides system information about the running process. This can be used to check the availability of the service, runtime information and operational metrics. By default the admin listener is configured on port 8088.
12+
13+
## Info
14+
15+
The `/info` endpoint provides basic information about the Optimizely Agent instance.
16+
17+
Example Request:
18+
```bash
19+
curl localhost:8088/info
20+
```
21+
22+
Example Response:
23+
```json
24+
{
25+
"version": "v0.10.0",
26+
"author": "Optimizely Inc.",
27+
"app_name": "optimizely"
28+
}
29+
```
30+
31+
## Health Check
32+
33+
The `/health` endpoint is used to determine service availability.
34+
35+
Example Request:
36+
```bash
37+
curl localhost:8088/health
38+
```
39+
40+
Example Response:
41+
```json
42+
{
43+
"status": "ok"
44+
}
45+
```
46+
47+
Agent will return a HTTP 200 - OK response if and only if all configured listeners are open and all external dependent services can be reached.
48+
A non-healthy service will return a HTTP 503 - Unavailable response with a descriptive message to help diagnose the issue.
49+
50+
This endpoint can used when placing Agent behind a load balancer to indicate whether a particular instance can receive inbound requests.
51+
52+
## Metrics
53+
54+
The `/metrics` endpoint exposes telemetry data of the running Optimizely Agent. The core runtime metrics are exposed via the go expvar package. Documentation for the various statistics can be found as part of the [mstats](https://golang.org/src/runtime/mstats.go) package.
55+
56+
Example Request:
57+
```bash
58+
curl localhost:8088/metrics
59+
```
60+
61+
Example Response:
62+
```json
63+
{
64+
"cmdline": [
65+
"bin/optimizely"
66+
],
67+
"memstats": {
68+
"Alloc": 924136,
69+
"TotalAlloc": 924136,
70+
"Sys": 71893240,
71+
"Lookups": 0,
72+
"Mallocs": 4726,
73+
"HeapAlloc": 924136,
74+
...
75+
"Frees": 172
76+
},
77+
...
78+
}
79+
```
80+
Custom metrics are also provided for the individual service endpoints and follow the pattern of:
81+
82+
```bash
83+
"timers.<metric-name>.counts": 0,
84+
"timers.<metric-name>.responseTime": 0,
85+
"timers.<metric-name>.responseTimeHist.p50": 0,
86+
"timers.<metric-name>.responseTimeHist.p90": 0,
87+
"timers.<metric-name>.responseTimeHist.p95": 0,
88+
"timers.<metric-name>.responseTimeHist.p99": 0,
89+
```

0 commit comments

Comments
 (0)