Last active
December 16, 2015 01:29
-
-
Save dohse/5355085 to your computer and use it in GitHub Desktop.
RTBKit bidding agent in node
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** bidding_agent_ex.cc -*- C++ -*- | |
Rémi Attab, 22 Feb 2013 | |
Copyright (c) 2013 Datacratic. All rights reserved. | |
Example of a simple fixed-price bidding agent. | |
*/ | |
#include "rtbkit/common/bids.h" | |
#include "rtbkit/core/banker/slave_banker.h" | |
#include "rtbkit/core/agent_configuration/agent_config.h" | |
#include "rtbkit/plugins/bidding_agent/bidding_agent.h" | |
#include "soa/service/service_utils.h" | |
#include <boost/program_options/cmdline.hpp> | |
#include <boost/program_options/options_description.hpp> | |
#include <boost/program_options/positional_options.hpp> | |
#include <boost/program_options/parsers.hpp> | |
#include <boost/program_options/variables_map.hpp> | |
#include <iostream> | |
#include <thread> | |
#include <chrono> | |
using namespace std; | |
using namespace ML; | |
namespace RTBKIT { | |
/******************************************************************************/ | |
/* FIXED PRICE BIDDING AGENT */ | |
/******************************************************************************/ | |
/** Simple bidding agent whose sole purpose in life is to bid 1$ CPM on every | |
bid requests it sees. It also has a very simple pacer which ensures that we | |
always have at most 1$ to spend every 10 seconds. | |
*/ | |
struct FixedPriceBiddingAgent : | |
public BiddingAgent | |
{ | |
FixedPriceBiddingAgent( | |
std::shared_ptr<Datacratic::ServiceProxies> services, | |
const string& serviceName) : | |
BiddingAgent(services, serviceName), | |
accountSetup(false) | |
{} | |
void init() | |
{ | |
// We only want to specify a subset of the callbacks so turn the | |
// annoying safety belt off. | |
strictMode(false); | |
onBidRequest = bind( | |
&FixedPriceBiddingAgent::bid, this, _1, _2, _3, _4, _5, _6); | |
// This component is used to speak with the master banker and pace the | |
// rate at which we spend our budget. | |
budgetController.init(getServices()->config); | |
budgetController.start(); | |
// Update our pacer every 10 seconds. Note that since this interacts | |
// with the budgetController which is only synced up with the router | |
// every few seconds, the wait period shouldn't be set too low. | |
addPeriodic("FixedPriceBiddingAgent::pace", 10.0, | |
[&] (uint64_t) { this->pace(); }); | |
BiddingAgent::init(); | |
} | |
void start() | |
{ | |
BiddingAgent::start(); | |
// Build our configuration and tell the world about it. | |
setConfig(); | |
} | |
void shutdown() | |
{ | |
BiddingAgent::shutdown(); | |
budgetController.shutdown(); | |
} | |
/** Sets up an agent configuration for our example. */ | |
void setConfig() | |
{ | |
config = AgentConfig(); | |
// Accounts are used to control the allocation of spending budgets for | |
// an agent. The whole mechanism is fully generic and can be setup in | |
// whatever you feel it bests suits you. For this example, I went for | |
// overly silly because that's how I roll. | |
config.account = {"a", "very", "long", "account", "name", "thingy"}; | |
// Specify the properties of the creatives we are trying to show. | |
config.creatives.push_back(Creative::sampleLB); | |
config.creatives.push_back(Creative::sampleWS); | |
config.creatives.push_back(Creative::sampleBB); | |
// Set our frequency cap to 42. This has two effects: 1) it instructs | |
// the router that we want bid requests destined for our agent to first | |
// be augmented with frequency capping information and 2) it instructs | |
// the frequency cap augmentor to tag any bid requests for which we've | |
// seen the user less the 42 times. | |
config.addAugmentation("frequency-cap-ex", Json::Value(42)); | |
// Instructs the router to only keep bid requests that have this tag. In | |
// other words keep only the bid requests that our agents has seen less | |
// then 42 times. | |
config.augmentationFilter.include.push_back("pass-frequency-cap-ex"); | |
// Tell the world about our config. We can change the configuration of | |
// an agent at any time by calling this function. | |
doConfig(config.toJson()); | |
} | |
/** Simple fixed price bidding strategy. Note that the router is in charge | |
of making sure we stay within budget and don't go bankrupt. | |
*/ | |
void bid( | |
double timestamp, | |
const Id & id, | |
std::shared_ptr<RTBKIT::BidRequest> br, | |
Bids bids, | |
double timeLeftMs, | |
const Json::Value & augmentations) | |
{ | |
for (Bid& bid : bids) { | |
// In our example, all our creatives are of the different sizes so | |
// there should only ever be one biddable creative. Note that that | |
// the router won't ask for bids on spots that don't have any | |
// biddable creatives. | |
ExcAssertEqual(bid.availableCreatives.size(), 1); | |
int availableCreative = bid.availableCreatives.front(); | |
// We don't really need it here but this is how you can get the | |
// AdSpot and Creative object from the indexes. | |
(void) br->spots[bid.spotIndex]; | |
(void) config.creatives[availableCreative]; | |
// Create a 2$ CPM bid with our available creative. Note that by | |
// default, the bid price is set to 0 which indicates that we don't | |
// wish to bid on the given spot. | |
bid.bid(availableCreative, USD_CPM(2)); | |
} | |
// A value that will be passed back to us when we receive the result of | |
// our bid. | |
Json::Value metadata; | |
metadata["html"] = "<tag></tag>"; | |
metadata["landingPageUrl"] = "https://www.fraport.de/"; | |
metadata["creativeName"] = "Name"; | |
metadata["advertiserName"] = "shameless selfplug"; | |
// Send our bid back to the agent. | |
doBid(id, bids, metadata); | |
} | |
/** Simple pacing scheme which allocates 1$ to spend every period. */ | |
void pace() | |
{ | |
// We need to register our account once with the banker service. | |
if (!accountSetup) { | |
accountSetup = true; | |
budgetController.addAccountSync(config.account); | |
} | |
// Make sure we have 1$ to spend for the next period. | |
budgetController.topupTransferSync(config.account, USD(1)); | |
} | |
AgentConfig config; | |
bool accountSetup; | |
SlaveBudgetController budgetController; | |
}; | |
} // namepsace RTBKIT | |
/******************************************************************************/ | |
/* MAIN */ | |
/******************************************************************************/ | |
int main(int argc, char** argv) | |
{ | |
using namespace boost::program_options; | |
Datacratic::ServiceProxyArguments args; | |
options_description options = args.makeProgramOptions(); | |
options.add_options() ("help,h", "Print this message"); | |
variables_map vm; | |
store(command_line_parser(argc, argv).options(options).run(), vm); | |
notify(vm); | |
if (vm.count("help")) { | |
cerr << options << endl; | |
return 1; | |
} | |
auto serviceProxies = args.makeServiceProxies(); | |
RTBKIT::FixedPriceBiddingAgent agent(serviceProxies, "fixed-price-agent-ex"); | |
agent.init(); | |
agent.start(); | |
while (true) this_thread::sleep_for(chrono::seconds(10)); | |
// Won't ever reach this point but this is how you shutdown an agent. | |
agent.shutdown(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var RTBkit = require('./build/x86_64/bin/rtb.node'); | |
var services = require('./build/x86_64/bin/services.node'); | |
var zookeeperUri = "localhost:2181"; // must point to same Zookeeper as routers | |
var services = new services.ServiceProxies(); | |
services.useZookeeper(zookeeperUri); | |
services.logToCarbon('localhost:2003'); | |
var agent = new RTBkit.BiddingAgent("myAgent", services); | |
agent.onBidRequest = function(){ | |
console.log('onBidRequest', arguments); | |
//agent.doBid(); | |
}; | |
agent.init(); | |
agent.start() | |
agent.doConfig({ | |
"account":[ | |
"a", | |
"very", | |
"long", | |
"account", | |
"name", | |
"thingy" | |
], | |
"augment":{ | |
"frequency-cap-ex":42, | |
"random":null | |
}, | |
"augmentationFilter":{ | |
"include":[ | |
"pass-frequency-cap-ex" | |
] | |
}, | |
"bidControl":{ | |
"fixedBidCpmInMicros":0, | |
"type":"RELAY" | |
}, | |
"creatives":[ | |
{ | |
"format":"728x90", | |
"id":2, | |
"name":"LeaderBoard", | |
"tagId":2 | |
}, | |
{ | |
"format":"160x600", | |
"id":0, | |
"name":"LeaderBoard", | |
"tagId":0 | |
}, | |
{ | |
"format":"300x250", | |
"id":1, | |
"name":"BigBox", | |
"tagId":1 | |
} | |
], | |
"errorFormat":"lightweight", | |
"lossFormat":"lightweight", | |
"minTimeAvailableMs":5.0, | |
"tagFilter":{ | |
"excludeIfNotPresent":false | |
}, | |
"test":false, | |
"winFormat":"full" | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{ | |
"exchangeType": "<exchange>", | |
"host": "localhost", | |
"port": 8080, | |
"threads": 4 | |
}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash -e | |
SERVICES=/dev/null | |
make -j4 build/x86_64/bin/{mbr_router_runner,bidding_agent_ex} \ | |
build/x86_64/bin/rtb.node | |
monitor_service_runner &>$SERVICES & | |
PIDS=($!) | |
trap 'kill ${PIDS[*]}' EXIT | |
agent_configuration_service_runner &>$SERVICES & | |
PIDS+=($!) | |
router_logger_runner &>/dev/null & | |
PIDS+=($!) | |
banker_service_runner --redis-uri localhost:6379 &>$SERVICES & | |
PIDS+=($!) | |
mbr_router_runner -nx exchange.json &>$SERVICES & | |
PIDS+=($!) | |
sleep 1 | |
$@ & | |
PIDS+=($!) | |
sleep 2 | |
curl http://localhost:8080/<exchange request fixture> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* mbr_router_runner.cc -*- C++ -*- | |
Jonas Dohse, 26 March 2013 | |
Copyright (c) 2013 mbr targeting GmbH. All rights reserved. | |
Start router by router runner | |
*/ | |
#include "jml/arch/timers.h" | |
#include "rtbkit/core/router/router_runner.h" | |
int main(int argc, char ** argv) { | |
RTBKIT::RouterRunnehr routerRunner; | |
routerRunner.doOptions(argc, argv); | |
routerRunner.init(); | |
routerRunner.start(); | |
while (true) { | |
ML::sleep(1.0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment