Skip to content

Commit 827c078

Browse files
committed
- gitignore update
- session update interval issue fixed - event duration constructor and public function added - sample app added
1 parent e1649db commit 827c078

File tree

9 files changed

+178
-40
lines changed

9 files changed

+178
-40
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# for out of source builds
22
build/
3+
.idea/
4+
.vscode/
5+
.project
36

47
# cmake generates these files
58
src/countly.hpp

CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ option(BUILD_SHARED_LIBS "Build shared libraries" ON)
1010
option(COUNTLY_USE_CUSTOM_HTTP "Use a custom HTTP library" OFF)
1111
option(COUNTLY_USE_SQLITE "Use SQLite" OFF)
1212
option(COUNTLY_BUILD_TESTS "Build test programs" OFF)
13+
option(COUNTLY_BUILD_SAMPLE "Build Sample programs" OFF)
1314

1415
if (NOT WIN32 AND NOT BUILD_SHARED_LIBS AND NOT COUNTLY_CUSTOM_HTTP)
1516
message(FATAL_ERROR "You must provide a custom HTTP function when compiling statically.")
@@ -72,3 +73,19 @@ if(COUNTLY_BUILD_TESTS)
7273
CXX_STANDARD_REQUIRED YES
7374
CXX_EXTENSIONS NO)
7475
endif()
76+
77+
if(COUNTLY_BUILD_SAMPLE)
78+
add_executable(countly-sample
79+
${CMAKE_CURRENT_SOURCE_DIR}/examples/example_integration.cpp)
80+
if(COUNTLY_USE_SQLITE)
81+
target_compile_definitions(countly-tests PRIVATE COUNTLY_USE_SQLITE)
82+
target_include_directories(countly-tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/sqlite)
83+
endif()
84+
target_include_directories(countly-sample PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/vendor/doctest/doctest)
85+
target_include_directories(countly-sample PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/vendor/json/include)
86+
target_link_libraries(countly-sample countly)
87+
set_target_properties(countly-sample PROPERTIES
88+
CXX_STANDARD 11
89+
CXX_STANDARD_REQUIRED YES
90+
CXX_EXTENSIONS NO)
91+
endif()

examples/example_integration.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#include <thread>
2+
#include <chrono>
3+
#include <random>
4+
#include <iostream>
5+
using namespace std;
6+
7+
8+
#include "countly.hpp"
9+
10+
void printLog(Countly::LogLevel level, const string& msg) {
11+
string lvl = "[DEBUG]";
12+
switch (level)
13+
{
14+
case Countly::LogLevel::DEBUG/* constant-expression */:
15+
/* code */
16+
lvl = "[Debug]";
17+
break;
18+
case Countly::LogLevel::INFO/* constant-expression */:
19+
/* code */
20+
lvl = "[INFO]";
21+
break;
22+
case Countly::LogLevel::WARNING/* constant-expression */:
23+
/* code */
24+
lvl = "[WARNING]";
25+
break;
26+
case Countly::LogLevel::ERROR/* constant-expression */:
27+
/* code */
28+
lvl = "[ERROR]";
29+
break;
30+
case Countly::LogLevel::FATAL/* constant-expression */:
31+
/* code */
32+
lvl = "[FATAL]";
33+
break;
34+
35+
default:
36+
break;
37+
}
38+
39+
cout<<lvl<<msg<<endl;
40+
}
41+
42+
43+
44+
int main() {
45+
cout<<"Sample App"<<endl;
46+
Countly& ct = Countly::getInstance();
47+
ct.alwaysUsePost(true);
48+
ct.setDeviceID("zahidzafar");
49+
50+
void (*logger_function)(Countly::LogLevel level, const std::string& message);
51+
logger_function = printLog;
52+
ct.setLogger(logger_function);
53+
// OS, OS_version, device, resolution, carrier, app_version);
54+
ct.SetMetrics("Windows 10", "10.22", "Mac", "800x600", "Carrier", "1.0");
55+
ct.setCustomUserDetails({{"Account Type", "Basic"}, {"Employer", "Company4"}});
56+
// Server and port
57+
ct.Start("8c1d653f8f474be24958b282d5e9b4c4209ee552", "https://master.count.ly", 443);
58+
ct.SetMaxEventsPerMessage(10);
59+
ct.SetMinUpdatePeriod(10);
60+
ct.setUpdateInterval(15);
61+
62+
bool flag = true;
63+
while (flag)
64+
{
65+
cout<<"Choose your option:"<<endl;
66+
cout<<"1) Basic Event"<<endl;
67+
cout<<"2) Event with count and sum"<<endl;
68+
cout<<"3) Event with count, sum, duration"<<endl;
69+
cout<<"4) Event with sum, count, duration and segmentation"<<endl;
70+
cout<<"0) Exit"<<endl;
71+
int a;
72+
cin>>a;
73+
switch (a)
74+
{
75+
case 1:
76+
ct.RecordEvent("Basic Event", 123);
77+
break;
78+
case 2:
79+
ct.RecordEvent("Event with count and sum", 644, 13.3);
80+
break;
81+
case 3: {
82+
Countly::Event event("Event with sum, count, duration", 1, 10, 60.5);
83+
ct.addEvent(event);
84+
break;
85+
}
86+
case 4: {
87+
std::map<std::string, std::string> segmentation;
88+
segmentation["height"] = "5.10";
89+
ct.RecordEvent("Event with sum, count, duration and segmentation", segmentation, 1, 0, 10);
90+
break;
91+
}
92+
case 0:
93+
flag = false;
94+
break;
95+
96+
default:
97+
cout<<"Option not found!"<<endl;
98+
break;
99+
}
100+
}
101+
102+
ct.updateSession();
103+
104+
return 0;
105+
}

examples/using_thread.cpp

Lines changed: 0 additions & 37 deletions
This file was deleted.

include/countly.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ class Countly {
115115
public:
116116
Event(const std::string& key, size_t count = 1);
117117
Event(const std::string& key, size_t count, double sum);
118+
Event(const std::string& key, size_t count, double sum, double duration);
118119

119120
void setTimestamp();
120121

@@ -196,6 +197,16 @@ class Countly {
196197

197198
addEvent(event);
198199
}
200+
201+
void RecordEvent(const std::string key, std::map<std::string, std::string> segmentation, int count, double sum, double duration) {
202+
Event event(key, count, sum, duration);
203+
204+
for (auto key_value: segmentation) {
205+
event.addSegmentation(key_value.first, json::parse(key_value.second));
206+
}
207+
208+
addEvent(event);
209+
}
199210
private:
200211
void log(LogLevel level, const std::string& message);
201212

src/countly.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ void Countly::setDeviceID(const std::string& value, bool same_user) {
182182

183183
void Countly::start(const std::string& app_key, const std::string& host, int port, bool start_thread) {
184184
mutex.lock();
185+
log(Countly::LogLevel::DEBUG, "[Countly][start]");
185186
this->host = host;
186187
if (host.find("http://") == 0) {
187188
use_https = false;
@@ -369,6 +370,7 @@ void Countly::flushEvents(std::chrono::seconds timeout) {
369370

370371
bool Countly::beginSession() {
371372
mutex.lock();
373+
log(Countly::LogLevel::DEBUG, "[Countly] [beginSession]");
372374
if (began_session) {
373375
mutex.unlock();
374376
return true;
@@ -408,6 +410,8 @@ bool Countly::beginSession() {
408410
}
409411

410412
bool Countly::updateSession() {
413+
log(Countly::LogLevel::DEBUG, "Countly::updateSession");
414+
411415
mutex.lock();
412416
if (!began_session) {
413417
mutex.unlock();
@@ -486,7 +490,7 @@ bool Countly::updateSession() {
486490
mutex.unlock();
487491
return false;
488492
}
489-
last_sent += duration;
493+
last_sent = Countly::getTimestamp();
490494
}
491495

492496
mutex.unlock();
@@ -530,6 +534,7 @@ bool Countly::updateSession() {
530534
}
531535

532536
bool Countly::endSession() {
537+
log(Countly::LogLevel::DEBUG, "[Countly] [endSession]");
533538
const std::chrono::system_clock::time_point now = Countly::getTimestamp();
534539
const auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
535540
const auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration(now));
@@ -626,6 +631,7 @@ static size_t countly_curl_write_callback(void *data, size_t byte_size, size_t n
626631
Countly::HTTPResponse Countly::sendHTTP(std::string path, std::string data) {
627632
bool use_post = always_use_post || (data.size() > COUNTLY_POST_THRESHOLD);
628633

634+
log(Countly::LogLevel::INFO, "[Countly] [sendHTTP] data: "+ data);
629635
if (!salt.empty()) {
630636
unsigned char checksum[SHA256_DIGEST_LENGTH];
631637
std::string salted_data = data + salt;
@@ -762,6 +768,8 @@ Countly::HTTPResponse Countly::sendHTTP(std::string path, std::string data) {
762768
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
763769
}
764770

771+
log(Countly::LogLevel::INFO, "[Countly][sendHTTP] request: " + full_url_stream.str());
772+
765773
std::string full_url = full_url_stream.str();
766774
curl_easy_setopt(curl, CURLOPT_URL, full_url.c_str());
767775

@@ -771,24 +779,26 @@ Countly::HTTPResponse Countly::sendHTTP(std::string path, std::string data) {
771779

772780
curl_code = curl_easy_perform(curl);
773781
if (curl_code == CURLE_OK) {
782+
774783
long status_code;
775784
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &status_code);
776785
response.success = (status_code >= 200 && status_code < 300);
777786
if (!body.empty()) {
778787
response.data = json::parse(body);
779788
}
780789
}
781-
782790
curl_easy_cleanup(curl);
783791
}
784792
#endif
793+
log(Countly::LogLevel::INFO, "[Countly][sendHTTP] response: " + response.data.dump());
785794
return response;
786795
#endif
796+
787797
}
788798

789799
std::chrono::system_clock::duration Countly::getSessionDuration(std::chrono::system_clock::time_point now) {
790800
mutex.lock();
791-
std::chrono::system_clock::duration duration = last_sent - now;
801+
std::chrono::system_clock::duration duration = now - last_sent;
792802
mutex.unlock();
793803
return duration;
794804
}
@@ -798,6 +808,7 @@ std::chrono::system_clock::duration Countly::getSessionDuration() {
798808
}
799809

800810
void Countly::updateLoop() {
811+
log(Countly::LogLevel::INFO, "[Countly][updateLoop]");
801812
mutex.lock();
802813
running = true;
803814
mutex.unlock();

src/event.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ Countly::Event::Event(const std::string& key, size_t count, double sum) : object
1111
object["sum"] = sum;
1212
}
1313

14+
Countly::Event::Event(const std::string& key, size_t count, double sum, double duration) : object({}), timer_running(false) {
15+
object["key"] = key;
16+
object["count"] = count;
17+
object["sum"] = sum;
18+
object["dur"] = duration;
19+
}
20+
1421
void Countly::Event::setTimestamp() {
1522
timestamp = Countly::getTimestamp();
1623
object["timestamp"] = std::chrono::duration_cast<std::chrono::seconds>(timestamp.time_since_epoch()).count();

tests/event.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ TEST_CASE("events are serialized correctly") {
5353
CHECK(event.serialize() == "{\"count\":3,\"key\":\"lose\",\"segmentation\":{\"points\":2000}}");
5454
}
5555

56+
SUBCASE("with count, sum, duration and segmentation") {
57+
Countly::Event event("lose", 3, 10, 100);
58+
event.addSegmentation("points", 2000);
59+
CHECK(event.serialize() == "{\"count\":3,\"dur\":100.0,\"key\":\"lose\",\"segmentation\":{\"points\":2000},\"sum\":10.0}");
60+
}
61+
5662
SUBCASE("with multibyte strings") {
5763
Countly::Event event("测试", 1);
5864
event.addSegmentation("苹果", "美味");

tests/main.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,21 @@ TEST_CASE("events are sent correctly") {
198198
CHECK(http_call.data["events"] == "[{\"count\":2,\"key\":\"win\"},{\"count\":1,\"key\":\"achievement\"}]");
199199
}
200200

201+
SUBCASE("event with count, sum, duration and segmentation is sent") {
202+
Countly::Event event("lose", 3, 10, 100);
203+
event.addSegmentation("points", 2000);
204+
countly.addEvent(event);
205+
206+
WAIT_FOR_SQLITE(1);
207+
countly.updateSession();
208+
209+
HTTPCall http_call = popHTTPCall();
210+
CHECK(!http_call.use_post);
211+
CHECK(http_call.data["app_key"] == COUNTLY_TEST_APP_KEY);
212+
CHECK(http_call.data["device_id"] == COUNTLY_TEST_DEVICE_ID);
213+
CHECK(http_call.data["events"] == "[{\"count\":3,\"dur\":100.0,\"key\":\"lose\",\"segmentation\":{\"points\":2000},\"sum\":10.0}]");
214+
}
215+
201216
SUBCASE("100 events are sent") {
202217
for (int i = 0; i < 100; i++) {
203218
Countly::Event event("click", i);

0 commit comments

Comments
 (0)