StatService.h
#pragma once
class StatService {
public:
StatService();
void trackPageView(const string &page);
void trackEvent(const string &eventName, map<string, string> &props);
private:
void getUrl(string url);
};
StatService.cpp
#include "StatService.h"
#include "GlobalConfig.h"
#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/NetworkInterface.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/StreamCopier.h>
#include <Poco/Path.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>
#include <Poco/Base64Encoder.h>
using namespace Poco::Net;
using namespace Poco;
using namespace std;
StatService::StatService() {
}
string GetIP() {
NetworkInterface::NetworkInterfaceList list = NetworkInterface::list();
for(NetworkInterface::NetworkInterfaceList::iterator i = list.begin(); i != list.end(); ++i) {
NetworkInterface nt = *i;
IPAddress addr = nt.address();
if(!addr.isLoopback()) {
return addr.toString();
}
}
return "";
}
void StatService::trackPageView(const string &page) {
const GlobalConfig *gConfig = GlobalConfig::GetInstance();
string eventName = "VisitPage";
stringstream ss;
ss << "{" <<
"\"event\":\"" << eventName << "\"," <<
"\"properties\": {" <<
"\"page\":\"" << page << "\"," <<
// "distinct_id" and "token" are
// special properties, described below.
"\"distinct_id\":" << "\"" << GetIP() << "\"," <<
"\"token\":\"" << gConfig->stat_token() << "\"";
ss << "}}";
//encode
std::ostringstream base64Str;
Base64Encoder encoder(base64Str);
encoder << ss.str();
encoder.close();
//cout << base64Str.str() << endl;
cout << ss.str() << endl;
ostringstream url;
url << gConfig->stat_endpoint() << "?data=" << base64Str.str();
string sUrl = url.str();
//cout << sUrl << endl;
sUrl.erase(remove_if(sUrl.begin(), sUrl.end(), isspace), sUrl.end());
//replaceAll(sUrl, "\n", "$");
//kick off
getUrl(sUrl);
}
void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}
void StatService::trackEvent(const string &eventName, map<string,string> &props) {
const GlobalConfig *gConfig = GlobalConfig::GetInstance();
stringstream ss;
ss << "{" <<
"\"event\":\"" << eventName << "\"," <<
"\"properties\": {" <<
// "distinct_id" and "token" are
// special properties, described below.
"\"distinct_id\":" << "\"" << GetIP() << "\"," <<
"\"token\":\"" << gConfig->stat_token() << "\"";
//plugin in properties
for(map<string,string>::const_iterator i = props.cbegin(); i != props.cend(); ++i) {
ss << ",\"" << i->first << "\":\"" << i->second << "\"";
}
ss << "}}";
//encode
std::ostringstream base64Str;
Base64Encoder encoder(base64Str);
encoder << ss.str();
encoder.close();
//cout << base64Str.str() << endl;
cout << ss.str() << endl;
ostringstream url;
url << gConfig->stat_endpoint() << "?data=" << base64Str.str();
string sUrl = url.str();
//cout << sUrl << endl;
sUrl.erase(remove_if(sUrl.begin(), sUrl.end(), isspace), sUrl.end());
//replaceAll(sUrl, "\n", "$");
//kick off
getUrl(sUrl);
}
void StatService::getUrl(string url) {
URI uri(url);
HTTPClientSession session(uri.getHost(), uri.getPort());
GlobalConfig * gConfig = GlobalConfig::GetInstance();
if(gConfig->proxy().size() > 0) {
session.setProxy(gConfig->proxy(), gConfig->proxy_port());
}
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
cout << "getUrl:path:" << path << endl;
// send request
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
session.sendRequest(req);
HTTPResponse res;
cout << res.getStatus() << " " << res.getReason() << endl;
// print response
istream &is = session.receiveResponse(res);
StreamCopier::copyStream(is, cout);
}