Skip to content

Commit b6aa925

Browse files
authored
Merge pull request #136 from Countly/manual_sessions
Manual sessions
2 parents 75f8d74 + c5ebc79 commit b6aa925

File tree

4 files changed

+84
-32
lines changed

4 files changed

+84
-32
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
## XX.XX.XX
1+
## XX.XX.XX
2+
- Added manual session control, which can be enabled via "Countly::enableManualSessionControl".
23
- Added "checkRQSize" function to return the current number of requests in the queue.
34

45
## 23.2.0

include/countly.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class Countly : public cly::CountlyDelegates {
5656

5757
void setSha256(cly::SHA256Function fun);
5858

59+
void enableManualSessionControl();
60+
5961
void setHTTPClient(HTTPClientFunction fun);
6062

6163
void setMetrics(const std::string &os, const std::string &os_version, const std::string &device, const std::string &resolution, const std::string &carrier, const std::string &app_version);
@@ -324,6 +326,7 @@ class Countly : public cly::CountlyDelegates {
324326
std::chrono::system_clock::duration getSessionDuration();
325327

326328
void updateLoop();
329+
void packEvents();
327330
bool began_session = false;
328331
bool is_being_disposed = false;
329332
bool is_sdk_initialized = false;

include/countly/countly_configuration.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ struct CountlyConfiguration {
6868

6969
SHA256Function sha256_function = nullptr;
7070

71+
bool manualSessionControl = false;
72+
7173
HTTPClientFunction http_client_function = nullptr;
7274

7375
nlohmann::json metrics;

src/countly.cpp

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ void Countly::setSha256(SHA256Function fun) {
128128
mutex->unlock();
129129
}
130130

131+
/**
132+
* Enable manual session handling.
133+
*/
134+
void Countly::enableManualSessionControl() {
135+
if (is_sdk_initialized) {
136+
log(LogLevel::WARNING, "[Countly][enableManualSessionControl] You can not enable manual session control after SDK initialization.");
137+
return;
138+
}
139+
140+
mutex->lock();
141+
configuration->manualSessionControl = true;
142+
mutex->unlock();
143+
}
144+
131145
void Countly::setMetrics(const std::string &os, const std::string &os_version, const std::string &device, const std::string &resolution, const std::string &carrier, const std::string &app_version) {
132146
if (is_sdk_initialized) {
133147
log(LogLevel::WARNING, "[Countly][setMetrics] You can not set metrics after SDK initialization.");
@@ -332,17 +346,19 @@ void Countly::_changeDeviceIdWithoutMerge(const std::string &value) {
332346

333347
// send all event to server and end current session of old user
334348
flushEvents();
335-
if (began_session) {
349+
if(!configuration->manualSessionControl){
336350
endSession();
337-
mutex->lock();
338-
session_params["device_id"] = value;
339-
mutex->unlock();
351+
}
352+
353+
mutex->lock();
354+
session_params["device_id"] = value;
355+
mutex->unlock();
356+
357+
// start a new session for new user
358+
if(!configuration->manualSessionControl){
340359
beginSession();
341-
} else {
342-
mutex->lock();
343-
session_params["device_id"] = value;
344-
mutex->unlock();
345360
}
361+
346362
}
347363
#pragma endregion Device Id
348364

@@ -387,7 +403,7 @@ void Countly::start(const std::string &app_key, const std::string &host, int por
387403
log(LogLevel::INFO, "[Countly][start] '_WIN32' is not defined");
388404
#endif
389405

390-
enable_automatic_session = start_thread;
406+
enable_automatic_session = start_thread && !configuration->manualSessionControl;
391407
start_thread = true;
392408

393409
if (port < 0 || port > 65535) {
@@ -422,9 +438,11 @@ void Countly::start(const std::string &app_key, const std::string &host, int por
422438

423439
if (!running) {
424440

425-
mutex->unlock();
426-
beginSession();
427-
mutex->lock();
441+
if(!configuration->manualSessionControl){
442+
mutex->unlock();
443+
beginSession();
444+
mutex->lock();
445+
}
428446

429447
if (start_thread) {
430448
stop_thread = false;
@@ -451,7 +469,7 @@ void Countly::startOnCloud(const std::string &app_key) {
451469

452470
void Countly::stop() {
453471
_deleteThread();
454-
if (began_session) {
472+
if (!configuration->manualSessionControl) {
455473
endSession();
456474
}
457475
}
@@ -593,8 +611,16 @@ bool Countly::attemptSessionUpdateEQ() {
593611
return false;
594612
}
595613
#endif
596-
597-
return !updateSession();
614+
bool result;
615+
if(!configuration->manualSessionControl){
616+
result = !updateSession();
617+
} else {
618+
log(LogLevel::WARNING, "[Countly][attemptSessionUpdateEQ] SDK is in manual session control mode. Please start a session first.");
619+
result = false;
620+
}
621+
622+
packEvents();
623+
return result;
598624
}
599625

600626
void Countly::clearEQInternal() {
@@ -656,6 +682,7 @@ bool Countly::beginSession() {
656682
log(LogLevel::INFO, "[Countly][beginSession]");
657683
if (began_session) {
658684
mutex->unlock();
685+
log(LogLevel::DEBUG, "[Countly][beginSession] Session is already active.");
659686
return true;
660687
}
661688

@@ -711,15 +738,42 @@ bool Countly::updateSession() {
711738
mutex->lock();
712739
if (!began_session) {
713740
mutex->unlock();
741+
if(configuration->manualSessionControl){
742+
log(LogLevel::WARNING, "[Countly][updateSession] SDK is in manual session control mode and there is no active session. Please start a session first.");
743+
return false;
744+
}
714745
if (!beginSession()) {
715746
// if beginSession fails, we should not try to update session
716747
return false;
717748
}
718749
mutex->lock();
719750
began_session = true;
720751
}
752+
753+
mutex->unlock();
754+
auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration());
755+
mutex->lock();
756+
757+
// report session duration if it is greater than the configured session duration value
758+
if (duration.count() >= configuration->sessionDuration) {
759+
log(LogLevel::DEBUG, "[Countly][updateSession] sending session update.");
760+
std::map<std::string, std::string> data = {{"app_key", session_params["app_key"].get<std::string>()}, {"device_id", session_params["device_id"].get<std::string>()}, {"session_duration", std::to_string(duration.count())}};
761+
requestModule->addRequestToQueue(data);
762+
763+
last_sent_session_request += duration;
764+
}
765+
} catch (const std::system_error &e) {
766+
std::ostringstream log_message;
767+
log_message << "update session, error: " << e.what();
768+
log(LogLevel::FATAL, log_message.str());
769+
}
770+
mutex->unlock();
771+
return true;
772+
}
721773

722-
// events array
774+
void Countly::packEvents() {
775+
try {
776+
// events array
723777
nlohmann::json events = nlohmann::json::array();
724778
std::string event_ids;
725779
mutex->unlock();
@@ -740,20 +794,7 @@ bool Countly::updateSession() {
740794
} else {
741795
log(LogLevel::DEBUG, "[Countly][updateSession] EQ empty.");
742796
}
743-
mutex->unlock();
744-
auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration());
745-
mutex->lock();
746-
747-
// report session duration if it is greater than the configured session duration value
748-
if (duration.count() >= configuration->sessionDuration) {
749-
log(LogLevel::DEBUG, "[Countly][updateSession] sending session update.");
750-
std::map<std::string, std::string> data = {{"app_key", session_params["app_key"].get<std::string>()}, {"device_id", session_params["device_id"].get<std::string>()}, {"session_duration", std::to_string(duration.count())}};
751-
requestModule->addRequestToQueue(data);
752-
753-
last_sent_session_request += duration;
754-
}
755-
756-
// report events if there are any to request queue
797+
// report events if there are any to request queue
757798
if (!no_events) {
758799
sendEventsToRQ(events);
759800
}
@@ -774,9 +815,9 @@ bool Countly::updateSession() {
774815
log(LogLevel::FATAL, log_message.str());
775816
}
776817
mutex->unlock();
777-
return true;
778818
}
779819

820+
780821
void Countly::sendEventsToRQ(const nlohmann::json &events) {
781822
log(LogLevel::DEBUG, "[Countly][sendEventsToRQ] Sending events to RQ.");
782823
std::map<std::string, std::string> data = {{"app_key", session_params["app_key"].get<std::string>()}, {"device_id", session_params["device_id"].get<std::string>()}, {"events", events.dump()}};
@@ -785,6 +826,10 @@ void Countly::sendEventsToRQ(const nlohmann::json &events) {
785826

786827
bool Countly::endSession() {
787828
log(LogLevel::INFO, "[Countly][endSession]");
829+
if(!began_session) {
830+
log(LogLevel::DEBUG, "[Countly][endSession] There is no active session to end.");
831+
return true;
832+
}
788833
const std::chrono::system_clock::time_point now = Countly::getTimestamp();
789834
const auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
790835
const auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration(now));
@@ -1125,6 +1170,7 @@ void Countly::updateLoop() {
11251170
if (enable_automatic_session) {
11261171
updateSession();
11271172
}
1173+
packEvents();
11281174
requestModule->processQueue(mutex);
11291175
}
11301176
mutex->lock();

0 commit comments

Comments
 (0)