Skip to content

Commit 24cb59a

Browse files
authored
Merge pull request #68 from reddit/update_decider_docs
Update docs
2 parents 5fb3e2c + 37e97a3 commit 24cb59a

File tree

3 files changed

+174
-73
lines changed

3 files changed

+174
-73
lines changed

Dockerfile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
FROM python:3.9
22

33
WORKDIR /src
4+
45
COPY requirements*.txt .
6+
COPY docs/requirements.txt ./doc-requirements.txt
7+
58
RUN pip install -r requirements.txt
9+
RUN pip install -r doc-requirements.txt
10+
611
CMD ["/bin/bash"]

docs/index.rst

Lines changed: 108 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,31 @@
11
``reddit_experiments``
22
===============================
33

4-
.. automodule:: reddit_experiments
4+
.. automodule:: reddit_decider
55

6-
Example
6+
7+
Prerequisite packages
78
-------
9+
.. code-block:: python
10+
11+
baseplate>=2.0.0
812
9-
To add the experiments client to your application, add the appropriate client
10-
declaration to your context configuration::
13+
reddit-edgecontext>=1.0.0
1114
12-
from reddit_decider import decider_client_from_config
13-
14-
decider = decider_client_from_config(
15-
app_config=app_config,
16-
event_logger=ExperimentLogger(),
17-
request_field_extractor=decider_field_extractor,
18-
)
19-
baseplate.add_to_context("decider", decider)
15+
# upgrade or integrate latest reddit-v2-events package
16+
# or manually update thrift schemas
17+
# to allow event fields to be populated in exposures
18+
reddit-v2-events
2019
21-
configure it in your application's configuration file:
20+
Prerequisite infrastructure
21+
-------
22+
Set up your service to pull down & synchronize experiment configurations from Zookeeper via the Baseplate `live-data watcher sidecar
23+
<https://baseplate.readthedocs.io/en/stable/api/baseplate/lib/live_data.html?highlight=sidecar#watcher-daemon>`_ (minimum v2.4.13).
24+
You'll have to make sure that your service is authorized to fetch the appropriate secret from Vault.
25+
26+
Prerequisite configuration:
27+
-------
28+
Setup :code:`reddit-experiments` in your application's configuration file:
2229

2330
.. code-block:: ini
2431
@@ -41,24 +48,102 @@ configure it in your application's configuration file:
4148
4249
...
4350
44-
and then use the attached :py:class:`~reddit_decider.Decider` object in
45-
request::
4651
47-
def my_method(request):
48-
if request.decider.get_variant("foo") == "bar":
49-
pass
52+
Integrate :code:`reddit-experiments` into Baseplate service
53+
-------
54+
In your service's initialization process, add a :code:`decider` instance to baseplate's context:
55+
(Note the use of the :code:`ExperimentLogger`, which is used to publish exposure V2 events,
56+
an example can be seen `here <https://github.snooguts.net/reddit/reddit-service-graphql/blob/3734b51732c29d07eef32aced86677cce5064dbb/graphql-py/graphql_api/events/utils.py#L205>`_)
5057

51-
Configuration
52-
-------------
58+
.. code-block:: python
5359
54-
.. autoclass:: DeciderClient
60+
# application code
61+
from reddit_decider import decider_client_from_config
62+
from reddit_decider import DeciderClient
5563
56-
.. autofunction:: decider_client_from_config
64+
# optional
65+
from some_file import my_field_extractor
66+
67+
68+
def make_wsgi_app(app_config):
69+
baseplate = Baseplate(app_config)
70+
decider_factory = decider_client_from_config(app_config=app_config,
71+
event_logger=ExperimentLogger,
72+
prefix="experiments.",
73+
request_field_extractor=my_field_extractor) # this is optional, can be `None` if edge_context contains all the fields you need
74+
baseplate.add_to_context("decider", decider_factory)
75+
76+
# Or use `DeciderClient` with `configure_context()`,
77+
# which internally calls `decider_client_from_config()`
78+
baseplate.configure_context({
79+
"decider": DeciderClient(
80+
prefix="experiments.",
81+
event_logger=EventLogger,
82+
request_field_extractor=my_field_extractor # optional
83+
})
84+
85+
Make sure :code:`edge_context` is accessible on :code:`request` object like so:
86+
87+
.. code-block:: python
88+
89+
request.edge_context
90+
91+
92+
[Optional] Define request field extractor function (`example <https://github.snooguts.net/reddit/reddit-service-graphql/blob/master/graphql-py/graphql_api/models/experiment.py#L67-L92>`_)
93+
94+
.. code-block:: python
5795
58-
Classes
96+
# Baseplate calls `make_object_for_context()` and creates a `DeciderContext`
97+
# which fetches the following fields from EdgeContext automatically:
98+
# - user_id
99+
# - device_id
100+
# - logged_in
101+
# - cookie_created_timestamp
102+
# - oauth_client_id
103+
# - country_code
104+
# - locale
105+
# - origin_service
106+
# - is_employee
107+
# - loid_created_ms
108+
109+
# Customized fields can be defined below to be extracted from a baseplate request
110+
# and will override above edge_context fields.
111+
112+
def my_field_extractor(request):
113+
# an example of customized baseplate request field extractor:
114+
return {"foo": request.headers.get("Foo"), "bar": "something"}
115+
116+
117+
Usage
59118
-------
119+
Use the attached :py:class:`~reddit_decider.Decider` object in request and
120+
:code:`decider.get_variant()` (which will automatically send an expose event)::
121+
122+
def my_method(request):
123+
if request.decider.get_variant("foo") == "bar":
124+
...
125+
126+
or optionally, if manual exposure is necessary, use::
127+
128+
def my_method(request):
129+
variant = request.decider.get_variant_without_expose(experiment_name='experiment_name')
130+
...
131+
request.decider.expose(experiment_name='experiment_name', variant_name=variant)
132+
133+
Configuration Classes
134+
-------------
135+
136+
.. autofunction:: decider_client_from_config
137+
138+
139+
.. autoclass:: DeciderClient
140+
60141
61142
.. autoclass:: DeciderContextFactory
62143
144+
145+
Decider API
146+
-------
147+
63148
.. autoclass:: Decider
64149
:members:

0 commit comments

Comments
 (0)