Skip to content

Commit 42b8ef8

Browse files
Processes batching and event threshold (#117)
* initial commit * config tests * checking if linting caused an error in windows * logs * name changes * Update example_integration.cpp * Update example_integration.cpp --------- Co-authored-by: ArtursKadikis <[email protected]>
1 parent 8300494 commit 42b8ef8

File tree

8 files changed

+97
-45
lines changed

8 files changed

+97
-45
lines changed

CHANGELOG.md

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,64 @@
1+
## xx.xx.x
2+
- Request queue processing now is limited to 100 requests at a time
3+
14
## 22.09.1
2-
* Mitigated a problem that caused invalid pointer error if the database path was set wrong
5+
- Mitigated a problem that caused invalid pointer error if the database path was set wrong
36

47
## 22.09.0
5-
* ! Minor breaking change ! SDK configuration now can't be changed after initialization/start
6-
* Added a persistent requests queue when building the SDK with the 'COUNTLY_USE_SQLITE' flag
7-
* Fixed a bug where view's name was being overriden by segmentation provided.
8+
- ! Minor breaking change ! SDK configuration now can't be changed after initialization/start
9+
- Added a persistent requests queue when building the SDK with the 'COUNTLY_USE_SQLITE' flag
10+
- Fixed a bug where view's name was being overriden by segmentation provided.
811

912
## 22.06.4
10-
* Fixed a bug where the SDK 'mutex' was being locked twice when built with the 'COUNTLY_USE_SQLITE' flag.
13+
- Fixed a bug where the SDK 'mutex' was being locked twice when built with the 'COUNTLY_USE_SQLITE' flag.
1114

1215
## 22.06.3
13-
* Fixed a bug where empty metrics were sent with session begin request.
16+
- Fixed a bug where empty metrics were sent with session begin request.
1417

1518
## 22.06.2
16-
* Fixed a bug where metrics were not sent with session begin request.
19+
- Fixed a bug where metrics were not sent with session begin request.
1720

1821
## 22.06.1
19-
* !! Major breaking change !! We are removing the 'LogLevel' enum out of the 'Countly' class which will change how that enum can be referenced. 'Countly::LogLevel' will not work, you will have to use 'cly::LogLevel' instead.
20-
* Added functionality to record crash.
21-
* Added ability to record breadcrumbs for crash recording.
22+
- !! Major breaking change !! We are removing the 'LogLevel' enum out of the 'Countly' class which will change how that enum can be referenced. 'Countly::LogLevel' will not work, you will have to use 'cly::LogLevel' instead.
23+
- Added functionality to record crash.
24+
- Added ability to record breadcrumbs for crash recording.
2225

2326
## 22.06.0
24-
* !! Major breaking change !! We are adding the 'cly' namespace on 'Countly' class which will change how that class can be referenced. 'Countly::' will not work, you will have to use 'cly::Countly::' instead.
25-
* !! Major breaking change !! We are extracting the 'Event' class out of the 'Countly' class which will change how that class can be referenced. 'Countly::Event' will not work, you will have to use 'cly::Event' instead.
26-
* !! Major breaking change !! Increased the compiler version required to compile the SDK. It's increased from version C++11 to C++14.
27-
* Making network requests has been reworked. They will now be sent on a separate thread. Requests will also be added in an internal queue and will be sent one at a time.
28-
* When making network requests, the SDK will now unlock it's mutex.
29-
* Fixed a bug that caused an exception on windows when encoding data that contains special characters.
27+
- !! Major breaking change !! We are adding the 'cly' namespace on 'Countly' class which will change how that class can be referenced. 'Countly::' will not work, you will have to use 'cly::Countly::' instead.
28+
- !! Major breaking change !! We are extracting the 'Event' class out of the 'Countly' class which will change how that class can be referenced. 'Countly::Event' will not work, you will have to use 'cly::Event' instead.
29+
- !! Major breaking change !! Increased the compiler version required to compile the SDK. It's increased from version C++11 to C++14.
30+
- Making network requests has been reworked. They will now be sent on a separate thread. Requests will also be added in an internal queue and will be sent one at a time.
31+
- When making network requests, the SDK will now unlock it's mutex.
32+
- Fixed a bug that caused an exception on windows when encoding data that contains special characters.
3033

3134
## 22.02.0
32-
* Added 10-second time-outs for all windows HTTP transactions.
33-
* Added ability to record views.
35+
- Added 10-second time-outs for all windows HTTP transactions.
36+
- Added ability to record views.
3437

3538
## 21.11.3
36-
* Added functionality to set custom SHA256.
39+
- Added functionality to set custom SHA256.
3740

3841
## 21.11.2
39-
* Fixed a bug that occurred after trying to erase events from the SQLite database when there were none.
40-
* Fixed a bug with the checksum calculation.
42+
- Fixed a bug that occurred after trying to erase events from the SQLite database when there were none.
43+
- Fixed a bug with the checksum calculation.
4144

4245
## 21.11.1
43-
* !! Major breaking change !! Fixed a bug that triggered when providing segmentation to the "RecordEvent" call. Previously, by mistake, every segmentation value was parsed as a JSON and threw an exception when it wasn't a valid JSON string.
46+
- !! Major breaking change !! Fixed a bug that triggered when providing segmentation to the "RecordEvent" call. Previously, by mistake, every segmentation value was parsed as a JSON and threw an exception when it wasn't a valid JSON string.
4447
Now this will not be the case and every String value can be provided. This is marked as a "major breaking change" in case some integrations were adding workarounds to this issue.
45-
* ! Minor breaking change ! Default automatic session update duration changed to 60 seconds.
46-
* Added a call to change the automatic session update duration.
47-
* Fixed a bug where session duration was reported wrong.
48-
* Fixed a bug that caused an exception when the application quit. This was due to the SDK attempting to send an end session request.
49-
* Fixed an issue with the custom HTTP client function pointer by setting it's default value.
50-
* Fixed a bug that caused GET requests to fail on Linux.
51-
* Fixed bug when changing device id with server merge.
52-
* Fixed bug when device id was changed without server merge. Previously the new session was started with the old device ID and not the new one.
53-
* Fixed a bug that was a typo ('COUNTLY_CUSTOM_HTTP' instead of 'COUNTLY_USE_CUSTOM_HTTP') in the cmake file that cause the SDK to be misconfigured.
54-
* Fixed a bug that caused POST requests to fail on Windows.
55-
* Fixed issues with location requests.
56-
* Deprecated old location calls and introduced a new location call
48+
- ! Minor breaking change ! Default automatic session update duration changed to 60 seconds.
49+
- Added a call to change the automatic session update duration.
50+
- Fixed a bug where session duration was reported wrong.
51+
- Fixed a bug that caused an exception when the application quit. This was due to the SDK attempting to send an end session request.
52+
- Fixed an issue with the custom HTTP client function pointer by setting it's default value.
53+
- Fixed a bug that caused GET requests to fail on Linux.
54+
- Fixed bug when changing device id with server merge.
55+
- Fixed bug when device id was changed without server merge. Previously the new session was started with the old device ID and not the new one.
56+
- Fixed a bug that was a typo ('COUNTLY_CUSTOM_HTTP' instead of 'COUNTLY_USE_CUSTOM_HTTP') in the cmake file that cause the SDK to be misconfigured.
57+
- Fixed a bug that caused POST requests to fail on Windows.
58+
- Fixed issues with location requests.
59+
- Deprecated old location calls and introduced a new location call
5760

5861
## 21.11.0
59-
* Fixed session duration issue.
60-
* Added functionality to report event duration manually.
61-
* 'startOnCloud' in 'Countly' is deprecated and this is going to be removed in the future.
62+
- Fixed session duration issue.
63+
- Added functionality to report event duration manually.
64+
- 'startOnCloud' in 'Countly' is deprecated and this is going to be removed in the future.

examples/example_integration.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,25 @@ void printLog(LogLevel level, const string &msg) {
3333
int main() {
3434
cout << "Sample App" << endl;
3535
Countly &ct = Countly::getInstance();
36+
// All configurations below are put here as an example
37+
// Your configuration in your app may be different
38+
// Please refer to the documentation for more information:
39+
// https://support.count.ly/hc/en-us/articles/4416163384857-C-
40+
3641
ct.alwaysUsePost(true);
3742
ct.setLogger(printLog);
3843
ct.SetPath("databaseFileName.db"); // this will be only built into account if the correct configurations are set
3944
ct.setDeviceID("test-device-id");
4045
// ct.setSalt("test-salt");
4146
// OS, OS_version, device, resolution, carrier, app_version);
4247
ct.SetMetrics("Windows 10", "10.22", "Mac", "800x600", "Carrier", "1.0");
43-
// Server and port
48+
49+
// start the SDK (initialize the SDK)
4450
ct.start("YOUR_APP_KEY", "https://try.count.ly", 443, true);
51+
4552
ct.SetMaxEventsPerMessage(10);
46-
ct.setAutomaticSessionUpdateInterval(5);
53+
ct.setAutomaticSessionUpdateInterval(5);// The value is set so low just for internal validation.
54+
ct.setMaxRQProcessingBatchSize(2); // in most cases not needed to be set. The value is set so low just for internal validation
4755

4856
ct.crash().addBreadcrumb("start");
4957

@@ -158,4 +166,4 @@ int main() {
158166
ct.stop();
159167

160168
return 0;
161-
}
169+
}

include/countly.hpp

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

4949
void setMaxRequestQueueSize(unsigned int requestQueueSize);
5050

51+
void setMaxRQProcessingBatchSize(unsigned int requestQueueProcessingSize);
52+
5153
void setSalt(const std::string &value);
5254

5355
void setLogger(void (*fun)(LogLevel level, const std::string &message));

include/countly/countly_configuration.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ struct CountlyConfiguration {
5050
*/
5151
unsigned int requestQueueThreshold = 1000;
5252

53+
/**
54+
* Set limit for the number of requests that can be processed at a time.
55+
*/
56+
unsigned int maxProcessingBatchSize = 100;
57+
5358
/**
5459
* Set the maximum amount of breadcrumbs.
5560
*/

src/countly.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ void Countly::setMaxRequestQueueSize(unsigned int requestQueueSize) {
6262
mutex->unlock();
6363
}
6464

65+
/**
66+
* Set limit for the number of requests that can be processed at a time.
67+
* If the limit is reached, the rest of the requests will be processed in the next cycle.
68+
* @param batchSize: max size of requests to process at a time
69+
*/
70+
void Countly::setMaxRQProcessingBatchSize(unsigned int batchSize) {
71+
mutex->lock();
72+
configuration->maxProcessingBatchSize = batchSize;
73+
mutex->unlock();
74+
}
75+
6576
void Countly::alwaysUsePost(bool value) {
6677
if (is_sdk_initialized) {
6778
log(LogLevel::WARNING, "[Countly][alwaysUsePost] You can not set the http method after SDK initialization.");
@@ -603,6 +614,7 @@ void Countly::flushEvents(std::chrono::seconds timeout) {
603614
log(LogLevel::FATAL, log_message.str());
604615
}
605616
}
617+
606618
#ifdef COUNTLY_BUILD_TESTS
607619
std::vector<std::string> Countly::debugReturnStateOfEQ() {
608620
try {
@@ -729,7 +741,7 @@ bool Countly::updateSession() {
729741
#else
730742
if (database_path.empty()) {
731743
mutex->unlock();
732-
log(LogLevel::FATAL, "Cannot fetch events, sqlite database path is not set");
744+
log(LogLevel::FATAL, "Cannot fetch events, sqlite database path is not set.");
733745
return false;
734746
}
735747

@@ -757,14 +769,16 @@ bool Countly::updateSession() {
757769
events.push_back(nlohmann::json::parse(table[(event_index * column_count) + 1]));
758770
}
759771

760-
log(LogLevel::DEBUG, "[Countly][updateSession] events count = " + events.size());
772+
log(LogLevel::DEBUG, "[Countly][updateSession] events count = " + std::to_string(events.size()));
761773

762774
event_id_stream.seekp(-1, event_id_stream.cur);
763775
event_id_stream << ')';
764776
event_ids = event_id_stream.str();
765777
} else if (return_value != SQLITE_OK) {
766778
log(LogLevel::ERROR, error_message);
767779
sqlite3_free(error_message);
780+
} else {
781+
log(LogLevel::DEBUG, "[Countly][updateSession] no events detected at the storage.");
768782
}
769783
sqlite3_free_table(table);
770784
}

src/request_module.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,21 +122,27 @@ void RequestModule::processQueue(std::shared_ptr<std::mutex> mutex) {
122122
impl->is_queue_being_processed = true;
123123
mutex->unlock();
124124

125+
// this counter is used to make sure that we don't get stuck in an infinite/long loop of request processing
126+
int processedRequestsCounter = 0;
127+
125128
while (true) {
126129
mutex->lock();
130+
impl->_logger->log(LogLevel::DEBUG, cly::utils::format_string("[RequestModule] processQueue: Processing the request queue."));
127131
if (impl->_storageModule->RQCount() == 0) {
132+
impl->_logger->log(LogLevel::DEBUG, cly::utils::format_string("[RequestModule] processQueue: Queue is empty."));
133+
128134
// stop sending requests once the queue is empty
129135
mutex->unlock();
130136
break;
131137
}
132138

133-
134139
std::shared_ptr<DataEntry> data = impl->_storageModule->RQPeekFront();
135140
mutex->unlock();
136141
HTTPResponse response = sendHTTP("/i", data->getData());
137142

138143
mutex->lock();
139144
if (!response.success) {
145+
impl->_logger->log(LogLevel::DEBUG, cly::utils::format_string("[RequestModule] processQueue: Failed to deliver to server, will try again later."));
140146
// if the request was not a success, abort sending and try again in the future
141147
mutex->unlock();
142148
break;
@@ -145,6 +151,13 @@ void RequestModule::processQueue(std::shared_ptr<std::mutex> mutex) {
145151
// we pop the front only if it is still the same request
146152
// the queue might have changed while we were sending the request
147153
impl->_storageModule->RQRemoveFront(data);
154+
processedRequestsCounter++;
155+
156+
if (processedRequestsCounter > impl->_configuration->maxProcessingBatchSize) {
157+
impl->_logger->log(LogLevel::DEBUG, cly::utils::format_string("[RequestModule] processQueue: Batch limit has been reached, will do next batch later."));
158+
mutex->unlock();
159+
break;
160+
}
148161

149162
mutex->unlock();
150163
}
@@ -328,4 +341,4 @@ HTTPResponse RequestModule::sendHTTP(std::string path, std::string data) {
328341
return response;
329342
#endif
330343
}
331-
} // namespace cly
344+
} // namespace cly

src/storage_module_memory.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ long long StorageModuleMemory::RQCount() {
5353
}
5454

5555
long long size = request_queue.size();
56-
_logger->log(LogLevel::DEBUG, "[Countly][StorageModuleMemory] RQCount size = " + size);
56+
_logger->log(LogLevel::DEBUG, "[Countly][StorageModuleMemory] RQCount size = [" + std::to_string(size) + "]");
5757
return size;
5858
}
5959

tests/config.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ TEST_CASE("Validate setting configuration values") {
4747
CHECK(config.sessionDuration == 60);
4848
CHECK(config.eventQueueThreshold == 100);
4949
CHECK(config.requestQueueThreshold == 1000);
50+
CHECK(config.maxProcessingBatchSize == 100);
5051
CHECK(config.breadcrumbsThreshold == 100);
5152
CHECK(config.forcePost == false);
5253
CHECK(config.port == 443);
@@ -74,6 +75,7 @@ TEST_CASE("Validate setting configuration values") {
7475
ct.setSalt("salt");
7576
ct.setMaxRequestQueueSize(10);
7677
ct.SetPath(TEST_DATABASE_NAME);
78+
ct.setMaxRQProcessingBatchSize(10);
7779
ct.start("YOUR_APP_KEY", "https://try.count.ly", 443, false);
7880

7981
// Get configuration values using Countly getters
@@ -88,6 +90,7 @@ TEST_CASE("Validate setting configuration values") {
8890
CHECK(config.sessionDuration == 5);
8991
CHECK(config.eventQueueThreshold == 10);
9092
CHECK(config.requestQueueThreshold == 10);
93+
CHECK(config.maxProcessingBatchSize == 10);
9194
CHECK(config.breadcrumbsThreshold == 100);
9295
CHECK(config.forcePost == true);
9396
CHECK(config.port == 443);
@@ -127,6 +130,7 @@ TEST_CASE("Validate setting configuration values") {
127130
ct.setAutomaticSessionUpdateInterval(5);
128131
ct.setSalt("salt");
129132
ct.setMaxRequestQueueSize(10);
133+
ct.setMaxRQProcessingBatchSize(10);
130134
ct.SetPath(TEST_DATABASE_NAME);
131135

132136
// Server and port
@@ -145,6 +149,7 @@ TEST_CASE("Validate setting configuration values") {
145149
CHECK(config.sessionDuration == 5);
146150
CHECK(config.eventQueueThreshold == 10);
147151
CHECK(config.requestQueueThreshold == 10);
152+
CHECK(config.maxProcessingBatchSize == 10);
148153
CHECK(config.breadcrumbsThreshold == 100);
149154
CHECK(config.forcePost == true);
150155
CHECK(config.port == 443);
@@ -168,6 +173,7 @@ TEST_CASE("Validate setting configuration values") {
168173
ct.setHTTPClient(new_CustomClient);
169174
ct.SetMetrics("Windows 11", "10", "p", "800x800", "Car", "1.1");
170175

176+
ct.setMaxRQProcessingBatchSize(50);
171177
ct.SetMaxEventsPerMessage(100);
172178
ct.setAutomaticSessionUpdateInterval(50);
173179
ct.setSalt("new-salt");
@@ -186,6 +192,7 @@ TEST_CASE("Validate setting configuration values") {
186192
CHECK(config.sessionDuration == 5);
187193
CHECK(config.eventQueueThreshold == 10);
188194
CHECK(config.requestQueueThreshold == 10);
195+
CHECK(config.maxProcessingBatchSize == 50); // this one should be changed after init
189196
CHECK(config.breadcrumbsThreshold == 100);
190197
CHECK(config.forcePost == true);
191198
CHECK(config.port == 443);

0 commit comments

Comments
 (0)