Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## XX.XX.XX
- Added manual session control, which can be enabled via "Countly::enableManualSessionControl".

## 23.2.0
- Request queue processing now is limited to 100 requests at a time
- Added 'setEventsToRQThreshold' method that sets the number of events after which all events will be sent to the RQ. Default value is set to 100.
Expand Down
3 changes: 3 additions & 0 deletions include/countly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class Countly : public cly::CountlyDelegates {

void setSha256(cly::SHA256Function fun);

void enableManualSessionControl();

void setHTTPClient(HTTPClientFunction fun);

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);
Expand Down Expand Up @@ -319,6 +321,7 @@ class Countly : public cly::CountlyDelegates {
std::chrono::system_clock::duration getSessionDuration();

void updateLoop();
void packEvents();
bool began_session = false;
bool is_being_disposed = false;
bool is_sdk_initialized = false;
Expand Down
2 changes: 2 additions & 0 deletions include/countly/countly_configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ struct CountlyConfiguration {

SHA256Function sha256_function = nullptr;

bool manualSessionControl = false;

HTTPClientFunction http_client_function = nullptr;

nlohmann::json metrics;
Expand Down
108 changes: 77 additions & 31 deletions src/countly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,20 @@ void Countly::setSha256(SHA256Function fun) {
mutex->unlock();
}

/**
* Enable manual session handling.
*/
void Countly::enableManualSessionControl() {
if (is_sdk_initialized) {
log(LogLevel::WARNING, "[Countly][enableManualSessionControl] You can not enable manual session control after SDK initialization.");
return;
}

mutex->lock();
configuration->manualSessionControl = true;
mutex->unlock();
}

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) {
if (is_sdk_initialized) {
log(LogLevel::WARNING, "[Countly][setMetrics] You can not set metrics after SDK initialization.");
Expand Down Expand Up @@ -332,17 +346,19 @@ void Countly::_changeDeviceIdWithoutMerge(const std::string &value) {

// send all event to server and end current session of old user
flushEvents();
if (began_session) {
if(!configuration->manualSessionControl){
endSession();
mutex->lock();
session_params["device_id"] = value;
mutex->unlock();
}

mutex->lock();
session_params["device_id"] = value;
mutex->unlock();

// start a new session for new user
if(!configuration->manualSessionControl){
beginSession();
} else {
mutex->lock();
session_params["device_id"] = value;
mutex->unlock();
}

}
#pragma endregion Device Id

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

enable_automatic_session = start_thread;
enable_automatic_session = start_thread && !configuration->manualSessionControl;
start_thread = true;

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

if (!running) {

mutex->unlock();
beginSession();
mutex->lock();
if(!configuration->manualSessionControl){
mutex->unlock();
beginSession();
mutex->lock();
}

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

void Countly::stop() {
_deleteThread();
if (began_session) {
if (!configuration->manualSessionControl) {
endSession();
}
}
Expand Down Expand Up @@ -593,8 +611,16 @@ bool Countly::attemptSessionUpdateEQ() {
return false;
}
#endif

return !updateSession();
bool result;
if(!configuration->manualSessionControl){
result = !updateSession();
} else {
log(LogLevel::WARNING, "[Countly][attemptSessionUpdateEQ] SDK is in manual session control mode. Please start a session first.");
result = false;
}

packEvents();
return result;
}

void Countly::clearEQInternal() {
Expand Down Expand Up @@ -656,6 +682,7 @@ bool Countly::beginSession() {
log(LogLevel::INFO, "[Countly][beginSession]");
if (began_session) {
mutex->unlock();
log(LogLevel::DEBUG, "[Countly][beginSession] Session is already active.");
return true;
}

Expand Down Expand Up @@ -711,15 +738,42 @@ bool Countly::updateSession() {
mutex->lock();
if (!began_session) {
mutex->unlock();
if(configuration->manualSessionControl){
log(LogLevel::WARNING, "[Countly][updateSession] SDK is in manual session control mode and there is no active session. Please start a session first.");
return false;
}
if (!beginSession()) {
// if beginSession fails, we should not try to update session
return false;
}
mutex->lock();
began_session = true;
}

mutex->unlock();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration());
mutex->lock();

// report session duration if it is greater than the configured session duration value
if (duration.count() >= configuration->sessionDuration) {
log(LogLevel::DEBUG, "[Countly][updateSession] sending session update.");
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())}};
requestModule->addRequestToQueue(data);

last_sent_session_request += duration;
}
} catch (const std::system_error &e) {
std::ostringstream log_message;
log_message << "update session, error: " << e.what();
log(LogLevel::FATAL, log_message.str());
}
mutex->unlock();
return true;
}

// events array
void Countly::packEvents() {
try {
// events array
nlohmann::json events = nlohmann::json::array();
std::string event_ids;
mutex->unlock();
Expand All @@ -740,20 +794,7 @@ bool Countly::updateSession() {
} else {
log(LogLevel::DEBUG, "[Countly][updateSession] EQ empty.");
}
mutex->unlock();
auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration());
mutex->lock();

// report session duration if it is greater than the configured session duration value
if (duration.count() >= configuration->sessionDuration) {
log(LogLevel::DEBUG, "[Countly][updateSession] sending session update.");
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())}};
requestModule->addRequestToQueue(data);

last_sent_session_request += duration;
}

// report events if there are any to request queue
// report events if there are any to request queue
if (!no_events) {
sendEventsToRQ(events);
}
Expand All @@ -774,9 +815,9 @@ bool Countly::updateSession() {
log(LogLevel::FATAL, log_message.str());
}
mutex->unlock();
return true;
}


void Countly::sendEventsToRQ(const nlohmann::json &events) {
log(LogLevel::DEBUG, "[Countly][sendEventsToRQ] Sending events to RQ.");
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()}};
Expand All @@ -785,6 +826,10 @@ void Countly::sendEventsToRQ(const nlohmann::json &events) {

bool Countly::endSession() {
log(LogLevel::INFO, "[Countly][endSession]");
if(!began_session) {
log(LogLevel::DEBUG, "[Countly][endSession] There is no active session to end.");
return true;
}
const std::chrono::system_clock::time_point now = Countly::getTimestamp();
const auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
const auto duration = std::chrono::duration_cast<std::chrono::seconds>(getSessionDuration(now));
Expand Down Expand Up @@ -1113,6 +1158,7 @@ void Countly::updateLoop() {
if (enable_automatic_session) {
updateSession();
}
packEvents();
requestModule->processQueue(mutex);
}
mutex->lock();
Expand Down
Loading