Skip to content

Commit 6445114

Browse files
committed
Add specific config stuff of plugin being set in the settings file.
Some minor changes for the ParameterPlugin interface to make it receive a config parameter. This config is get from the settings file and is specific of each plug in(can have anything). Also make the openrtb plugin independent of the mopub exchange. The next step will be to make rubicon from this one. Aslo add initial Readme file. Add mopub specific settings for the openrtb plugin under settings/mopub_config.py Also click notifications for the openrtb plugin.
1 parent c7cba53 commit 6445114

10 files changed

+125
-45
lines changed

README

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Requirements
22
============
33

4-
- libev (from source, > 4.15)
4+
- libev (from source, > 4.15) put to make an easy install ./configure --prefix=/usr
55
- pyev
66
- http_parser
7-
7+
- mako
88

exchange/exchange.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from settings import MAX_CONNS, MAX_EVENT_CONNS, CHECK_CONNS_TO, CHECK_PENDING_TO, \
1515
TEMPLATE_FILENAME, EVENT_ENDPOINT, PARAMETER_PLUGIN, \
1616
KEEP_ALIVE_HTTP_REQUEST, EVENT_CONN_KEEP_ALIVE_TO, \
17-
PLUGIN_DO_TO, REPORT_WINS
17+
PLUGIN_DO_TO, REPORT_WINS, PLUGIN_CONFIG
1818

1919
from rtb import RTBRequestFactory
2020
from adserver import AdServer
@@ -78,7 +78,9 @@ def __init__(self, dsp_endpoints, event_endpoint, balance_conn_timeout):
7878
TEMPLATE_FILENAME)
7979
self.adserver = AdServer(self.loop)
8080
self.request_fact.initialize()
81-
self.request_fact.set_parameter_plug(PARAMETER_PLUGIN, self.adserver)
81+
self.request_fact.set_parameter_plug(PARAMETER_PLUGIN,
82+
self.adserver,
83+
PLUGIN_CONFIG)
8284
if PLUGIN_DO_TO:
8385
self.watchers.append(pyev.Timer(
8486
PLUGIN_DO_TO,

plugin/datacratic_plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class DatacraticPlugin(ParameterPlugin):
1515
def __init__(self):
1616
self.aid = None
1717

18-
def initialize(self, adserver):
18+
def initialize(self, adserver, config):
1919
self.adserver = adserver
2020

2121
def get_request(self):

plugin/openrtb_plugin.py

+61-31
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,6 @@
55
import logging
66
from urlparse import urlparse
77

8-
# CONFIG (see to put this in any other part; aka not global)
9-
from render_utils import incrementor
10-
RENDER_MAP = {
11-
'auction_id' : incrementor(12345678)}
12-
BODY_TEMPLATES = ['plugin/mopub/mopub_body1.tmpl',
13-
'plugin/mopub/mopub_body2.tmpl']
14-
HEH_ENDPOINT_TMPL = "http://localhost:8080/impression/${exchange}/${AUCTION_ID}/${AUCTION_PRICE}?impid=${AUCTION_IMP_ID}"
15-
AD_SERVER_ENDPOINT_TMPL = "http://localhost:8080/events?ev=imp&aid=${AUCTION_ID}&apr=${AUCTION_PRICE}&sptid=${AUCTION_IMP_ID}"
16-
USE_HEH_ENDPOINT = False
17-
HTTP_RESOURCE = 'mopub'
18-
198

209
class OpenRTBPlugin(ParameterPlugin):
2110
'''
@@ -24,34 +13,42 @@ class OpenRTBPlugin(ParameterPlugin):
2413
def __init__(self):
2514
self.request_body_templates = []
2615
self.render_map = {}
27-
self.tmpl_notif = ''
16+
self.tmpl_imp_notif = ''
2817

29-
def initialize(self, adserver):
18+
def initialize(self, adserver, config):
3019

3120
self.adserver = adserver
21+
self.http_resource = config['http_resource']
22+
self.exchange = config['exchange']
3223

33-
self.render_map = RENDER_MAP
34-
self.request_body_templates_files = BODY_TEMPLATES
24+
# Map to render the bid request body templates
25+
self.render_map = config['render_map']
3526

36-
# Create templates...
27+
# Create templates fot the bid requests...
28+
self.request_body_templates_files = config['req_body_templates']
3729
for filename in self.request_body_templates_files:
3830
with open(filename) as f:
3931
logging.info('Using file template %s' % filename)
4032
tmpl = Template(''.join(f.readlines()))
4133
self.request_body_templates.append(tmpl)
4234

43-
# Template for notification endpoint
44-
if USE_HEH_ENDPOINT :
45-
self.tmpl_notif_file = HEH_ENDPOINT_TMPL
35+
# Templates for notification endpoint
36+
if config['use_heh_endpoint'] :
37+
self.tmpl_imp_notif_file = config['heh_endpt_imp_tmpl']
38+
self.tmpl_click_notif_file = config['heh_endpt_click_tmpl']
4639
else :
47-
self.tmpl_notif_file = AD_SERVER_ENDPOINT_TMPL
48-
self.tmpl_notif = Template(self.tmpl_notif_file)
40+
self.tmpl_imp_notif_file = config['adserver_endpt_imp_tmpl']
41+
self.tmpl_click_notif_file = config['adserver_endpt_click_tmpl']
42+
43+
# Create the templates for the notifications
44+
self.tmpl_imp_notif = Template(self.tmpl_imp_notif_file)
45+
self.tmpl_click_notif = Template(self.tmpl_click_notif_file)
4946

5047
def get_request(self):
51-
# We need to return a request line, a map of headers and a body string
48+
# We need to return a request line, a map of headers and a body
5249

5350
# Create the request line
54-
req_line = 'POST /%s HTTP/1.1' % HTTP_RESOURCE
51+
req_line = 'POST /%s HTTP/1.1' % self.http_resource
5552

5653
# Set the headers
5754
headers = {}
@@ -81,19 +78,53 @@ def receive_response(self, status_code, headers, body):
8178
js = json.loads(body)
8279
logging.debug("Response received :")
8380
logging.debug(str(js))
84-
price = js['seatbid'][0]['bid'][0]['price']
85-
auction_id = js['id']
86-
spot_id = js['seatbid'][0]['bid'][0]['impid']
81+
price = self.get_auction_price(js)
82+
auction_id = self.get_auction_id(js)
83+
spot_id = self.get_auction_impression_id(js)
8784

8885
# With that data, create the notification...
8986
notif_render = { 'AUCTION_PRICE' : price,
9087
'AUCTION_ID' : auction_id,
9188
'AUCTION_IMP_ID' : spot_id,
92-
'exchange' : 'mopub'}
93-
url = self.tmpl_notif.substitute(notif_render)
89+
'exchange' : self.exchange }
90+
91+
# Win notification...
92+
url = self.tmpl_imp_notif.substitute(notif_render)
9493
self.__send_impression_notification(url)
94+
95+
# Click notification...
96+
click_url = self.tmpl_click_notif.substitute(notif_render)
97+
self.__send_click_notification(click_url)
98+
9599
return (False, '', {}, '')
96100

101+
def get_auction_price(self, json_response):
102+
return json_response['seatbid'][0]['bid'][0]['price']
103+
104+
def get_auction_id(self, json_response):
105+
return json_response['id']
106+
107+
def get_auction_impression_id(self, json_response):
108+
return json_response['seatbid'][0]['bid'][0]['impid']
109+
110+
def __send_click_notification(self, url):
111+
112+
# Only generate clicks for the 2% of the cases
113+
if random.random < 0.98:
114+
return
115+
116+
parsed_url = urlparse(url)
117+
req_line = 'GET %s?%s HTTP/1.1' % (parsed_url.path,
118+
parsed_url.query)
119+
headers = {}
120+
headers['Host'] = 'localhost'
121+
heads = self.__headers_to_str(headers)
122+
buf = '%s\r\n%s\r\n' % (req_line, heads)
123+
124+
# send the impression event in 0.1 secs
125+
logging.debug("Sending click notification :")
126+
logging.debug(buf)
127+
self.adserver.send_event(buf, 0.1)
97128

98129
def __send_impression_notification(self, url):
99130
parsed_url = urlparse(url)
@@ -105,7 +136,7 @@ def __send_impression_notification(self, url):
105136
buf = '%s\r\n%s\r\n' % (req_line, heads)
106137

107138
# send the impression event in 0.1 secs
108-
logging.debug("Sending notification :")
139+
logging.debug("Sending impression notification :")
109140
logging.debug(buf)
110141
self.adserver.send_event(buf, 0.1)
111142

@@ -115,9 +146,8 @@ def __headers_to_str(self, headers):
115146
heads += '%s: %s\r\n' % (k, v)
116147
return heads
117148

118-
119149
def receive_win_response(self, status_code, headers, body):
120150
logging.debug('received_win_response')
121151

122152
def do(self, watcher, revents):
123-
logging.info('doing...')
153+
logging.debug('doing...')

plugin/parameter_plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class ParameterPlugin(object):
55
def __init__(self):
66
pass
77

8-
def initialize(self, adserver):
8+
def initialize(self, adserver, config):
99
raise NotImplementedError('initialize must be implemeted')
1010

1111
def get_request(self):

plugin/rubicon_plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self):
4545
self.request_templates = []
4646
self.aid = None
4747

48-
def initialize(self, adserver):
48+
def initialize(self, adserver, config):
4949
self.adserver = adserver
5050
for name in REQUEST_FILES:
5151
with open(os.path.join(BASE_PATH, name), 'rb') as f:

rtb/request_factory.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ def initialize(self):
1818
# read the template file
1919
self.template = Template(filename=self.template_file)
2020

21-
def set_parameter_plug(self, plugin, adserver):
21+
def set_parameter_plug(self, plugin, adserver, config):
2222
'''
2323
Set a param class plugin, this must implement
2424
the ParameterPlugin interface
2525
'''
2626
self.plugin_instance = plugin()
27-
self.plugin_instance.initialize(adserver)
27+
self.plugin_instance.initialize(adserver, config)
2828

2929
def create_request(self, set_aid=True):
3030
'''

settings/mopub_config.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
from render_utils import incrementor
2+
3+
conf = {
4+
5+
# Name of the exchange being simulated (used to generate notifications)
6+
# in the correct path
7+
'exchange' : 'mopub',
8+
9+
# This define the body templates that are being sent to the rtbkit
10+
# exchange connector endpoint (files).
11+
'req_body_templates' : [
12+
'plugin/mopub/mopub_body1.tmpl',
13+
'plugin/mopub/mopub_body2.tmpl'
14+
],
15+
16+
# This map defines a list of functions that when being called return a
17+
# value to be rendered in the templates defined in the
18+
# 'req_body_templates' field. For example to return a constant value
19+
# 'auction_id' : lambda : 5 (will return always five)
20+
'render_map' : {
21+
'auction_id' : incrementor(12345678)
22+
},
23+
24+
# Definde what resource of the exchange connector endpoint is hitted
25+
# in order to place a bid request.
26+
'http_resource' : 'mopub',
27+
28+
# Define the url where the notifications of impressions and clicks will
29+
# be send. By this, the adm field is not have in count. The ip and
30+
# port set it here are replaced by global parameters of the endpoint
31+
# settings.
32+
'adserver_endpt_imp_tmpl' : "http://localhost:8080/events?ev=imp&aid=${AUCTION_ID}&apr=${AUCTION_PRICE}&sptid=${AUCTION_IMP_ID}",
33+
'adserver_endpt_click_tmpl' : "http://localhost:8080/events?ev=cli&aid=${AUCTION_ID}&sptid=${AUCTION_IMP_ID}",
34+
35+
# If set to true, instead of using the 'adserver_endpt_imp_tmpl' and
36+
# 'adserver_endpt_click_tmpl', it will use the following heh templates
37+
# in order to hit heh instead of the ad server connector directly.
38+
'use_heh_endpoint' : False,
39+
'heh_endpt_imp_tmpl' : "http://localhost:8080/impression/${exchange}/${AUCTION_ID}/${AUCTION_PRICE}?impid=${AUCTION_IMP_ID}",
40+
'heh_endpt_click_tmpl' : "http://localhost:8080/click/${exchange}/${AUCTION_ID}?impid=${AUCTION_IMP_ID}"
41+
42+
}
File renamed without changes.

settings/settings.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Plugin imports
44
from plugin.rubicon_plugin import RubiconPlugin
55
from plugin.datacratic_plugin import DatacraticPlugin
6+
from plugin.openrtb_plugin import OpenRTBPlugin
67

78
# Max connections for bid requests allowed for the process
89
MAX_CONNS = 1
@@ -13,12 +14,12 @@
1314
# - endpoint should be a string 'host:port'
1415
# - expected_qps is the amount of qps expected for the endpoint
1516
ENDPOINT_LIST = [
16-
('localhost:12339', 100),
17+
('10.0.2.21:12340', 20),
1718
]
1819

1920
# Event endpoint :
2021
# - endpoint should be a string 'host:port'
21-
EVENT_ENDPOINT = 'localhost:12340'
22+
EVENT_ENDPOINT = '10.0.2.21:12350'
2223

2324
# Balance time out indicating the period in seconds
2425
# to balance connections
@@ -33,7 +34,7 @@
3334

3435
# Timeout in seconds to periodically invoke the plugin.do method
3536
# set to None if it does not need to be invoked
36-
PLUGIN_DO_TO = 2
37+
PLUGIN_DO_TO = 10
3738

3839
# Report wps statistics
3940
REPORT_WINS = False
@@ -53,10 +54,15 @@
5354
# - logging.INFO
5455
# - logging.WARNING
5556
# - logging.ERROR
56-
LOG_LEVEL = logging.INFO
57+
LOG_LEVEL = logging.DEBUG
5758

5859
# Parameter plugin
59-
PARAMETER_PLUGIN = RubiconPlugin
60+
#PARAMETER_PLUGIN = RubiconPlugin
61+
PARAMETER_PLUGIN = OpenRTBPlugin
62+
63+
# Configuration map that will be passed in the initialize
64+
import mopub_config
65+
PLUGIN_CONFIG = mopub_config.conf
6066

6167
# RTB request template filename
6268
TEMPLATE_FILENAME = 'templates/request.template'

0 commit comments

Comments
 (0)