Skip to content

Commit

Permalink
[SDK 712] Backend mode feature added. (#15)
Browse files Browse the repository at this point in the history
* Basic structure

* Removed previous code

* - sessions, event, views, crash and user request added into q
- request q process

* - Sample App added

* - record user properties method updated
- Sample app updated

* Backend mode events unit tests added.

* - views
- sessions (end, update, begin)
- crash
- user properties
Unit tests added.

* BackendMode import in Countly

* Stable Code point

* - Config unit test added
- Unit tests init changed

* SDK Core feature will not work if backend mode is enabled.

* - Example app updated
- Changelog added

* Sample App updated
Config updated

* - session calls moved into switch
- interal calss added to recrod data
- ConfigTests2.java removed
- Change log updated

* - Getter Setter removed

* logs call updated to spec not java sdk.

* - Logs and message updated
- Unit tests updated (common event and request time validate method)
-  Map<String, String> ---> Map<String, Object>
- Sample App updated

* - metrics param added in session begin
- unit test for session begin metrics
- Unit tests comments added and method renamed
- Exception on other unit tests fixed

* - 'requestQueueMaxSize' field added in configuration
- Process request qu logic remvoed form 'BackendModeModule' and moved to SDKCore
- Views Invalid data unit tests Added
- Events invalid data unit tests added
- Sessions (begin, update, end) invalid data unit tests added.

* - record exception invalid data unit tests added
- recrod user properties invalid data unit tests added
- Segmentation data validatio added (Views, Events, user detial, exceptions)

* segmentation invalid data type unit tests added for Events, Veiws, user, exceptoin.

* segmentation validation for user properties.

* - userProperteis restructure logic added
- unit tests added.

* - Sample app updated
- process request signal added
- null pointer bug fixed

* - record direct request
- unit tests added.

* - sdk_name, sdk_version, checksum protected
- drop reqeust logic added

* Sample updated
userdetail internal call logic updated
userdetail unit tests added
MaxRequestQSize lower limit logic added
PR Changes

* smaple app updated

* - Example app updated
- logs updated

* - example updated
- method documentation added
- timestamp datatype updated

* - getQueueSize moved to BackendMode class
- code formating

* getQueueSize = request queue + event queue
assert added in unit tests

* version updated to 20.11.2-RC1

* formating fixed

* Tweaking releasing things

* Sum bug fixed!

* record event sum data type updated

* performance unit test

* request queue size = 1000000

* perfomance unit test reverted
performance test sample app added.

* stop on performing test

* Example updated

* time and count info added

* Log updated

* redundant removed from user detail unit tests.

* Performance test updated
Backend mode example updated
Error print if reqeust queue size is lessthan 1

* - Crash detail added while recording crash
- Crash unit tests
- Backend mode sample app updated
- Backend Mode performance app updated

* Default folder path added

* Mehods documenation added.

* Event duration data type udpatd from 'double' to 'Double'
unit tests updated
example app updated

* time calculation move outside switch
backend mode enable check added.

* moved related unit test in single unit test
extra unit tests removed

* sesseion begin location added

* session Location added
session location unit tests added

* Version updated to '20.11.2'
BackendMode 'disableMode'check added
Unit test function name updated

Co-authored-by: Zahid Zafar <>
Co-authored-by: ArtursK <kadikis.arturs@gmail.com>
  • Loading branch information
ZahidZafar and ArtursKadikis authored Apr 20, 2022
1 parent aad711b commit ca61a7b
Show file tree
Hide file tree
Showing 30 changed files with 2,436 additions and 246 deletions.
12 changes: 0 additions & 12 deletions .idea/runConfigurations.xml

This file was deleted.

124 changes: 124 additions & 0 deletions .idea/uiDesigner.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
20.11.2
* Added backend mode feature and a new configuration field to enable it.

20.11.1
* Fixed a bug related to server response handling.
* Fixed a potential issue with parameters tampering protection while adding checksum.
Expand Down
203 changes: 203 additions & 0 deletions app-java/src/main/java/ly/count/java/demo/BackendModeExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
package ly.count.java.demo;

import ly.count.sdk.java.Config;
import ly.count.sdk.java.Countly;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class BackendModeExample {
final static String DEVICE_ID = "device-id";
final static String COUNTLY_APP_KEY = "YOUR_APP_KEY";
final static String COUNTLY_SERVER_URL = "https://try.count.ly/";

static void recordDataWithLegacyCalls() {
// Record Event
Countly.api().event("Event With Sum And Count")
.setSum(23)
.setCount(2).record();

// Record view
Countly.api().view("Start view");

// Record Location
Countly.api().addLocation(31.5204, 74.3587);

// Record user properties
Countly.api().user().edit()
.setName("Full name")
.setUsername("nickname")
.setEmail("test@test.com")
.setOrg("Tester")
.setPhone("+123456789")
.commit();

// Record crash
try {
int a = 10 / 0;
} catch (Exception e) {
Countly.api().addCrashReport(e, false, "Divided by zero", null, "sample app");
}

}

public static void main(String[] args) throws Exception {

Scanner scanner = new Scanner(System.in);

Config config = new Config(COUNTLY_SERVER_URL, COUNTLY_APP_KEY)
.setLoggingLevel(Config.LoggingLevel.DEBUG)
.enableBackendMode()
.setRequestQueueMaxSize(10000)
.setDeviceIdStrategy(Config.DeviceIdStrategy.UUID)
.setRequiresConsent(false)
.setEventsBufferSize(1000);

// Countly needs persistent storage for requests, configuration storage, user profiles and other temporary data,
// therefore requires a separate data folder to run

File targetFolder = new File("d:\\__COUNTLY\\java_test\\");

// Main initialization call, SDK can be used after this one is done
Countly.init(targetFolder, config);
boolean running = true;
while (running) {

System.out.println("Choose your option: ");

System.out.println("1) Record an event with key, count, sum, duration and segmentation");
System.out.println("2) Record a view");
System.out.println("3) Record user properties");
System.out.println("4) Record an exception with throwable and segmentation");
System.out.println("5) Record an exception with message, stacktrace and segmentation");
System.out.println("6) Start session");
System.out.println("7) Update session");
System.out.println("8) End session");
System.out.println("9) Record a direct request");
System.out.println("99) Record data with legacy calls");
System.out.println("0) Exit ");

int input = scanner.nextInt();
switch (input) {
case 0:
running = false;
break;
case 1: { // Record an event with key, count, sum, duration and segmentation
Map<String, Object> segment = new HashMap<String, Object>() {{
put("Time Spent", 60);
put("Retry Attempts", 60);
}};

Countly.backendMode().recordEvent(DEVICE_ID, "Event Key", 1, 0.1, 5.0, segment, null);
}
break;
case 2: { // Record a view
Map<String, Object> segmentation = new HashMap<String, Object>() {{
put("visit", "1");
put("segment", "Windows");
put("start", "1");
}};

Countly.backendMode().recordView(DEVICE_ID, "SampleView", segmentation, 1646640780130L);
}
break;
case 3: { // record user detail and properties
Map<String, Object> userDetail = new HashMap<>();
userDetail.put("name", "Full Name");
userDetail.put("username", "username1");
userDetail.put("email", "user@gmail.com");
userDetail.put("organization", "Countly");
userDetail.put("phone", "000-111-000");
userDetail.put("gender", "M");
userDetail.put("byear", "1991");
//custom detail
userDetail.put("hair", "black");
userDetail.put("height", 5.9);
userDetail.put("fav-colors", "{$push: black}");
userDetail.put("marks", "{$inc: 1}");

Countly.backendMode().recordUserProperties(DEVICE_ID, userDetail, null);
}
break;
case 4: { // record an exception with throwable and segmentation
Map<String, Object> segmentation = new HashMap<String, Object>() {{
put("login page", "authenticate request");
}};
Map<String, String> crashDetails = new HashMap<String, String>() {{
put("_os", "Windows 11");
put("_os_version", "11.202");
put("_logs", "main page");
}};
try {
int a = 10 / 0;
} catch (Exception e) {
Countly.backendMode().recordException(DEVICE_ID, e, segmentation, crashDetails, null);
}
}
break;
case 5: { // record an exception with message, stacktrace and segmentation
Map<String, Object> segmentation = new HashMap<String, Object>() {{
put("login page", "authenticate request");
}};

Map<String, String> crashDetails = new HashMap<String, String>() {{
put("_os", "Windows 11");
put("_os_version", "11.202");
put("_logs", "main page");
}};
try {
int a = 10 / 0;
} catch (Exception e) {
Countly.backendMode().recordException(DEVICE_ID, "Divided By Zero", "stack traces", segmentation, crashDetails, null);
}
}
break;
case 6: { // start a session
Map<String, String> metrics = new HashMap<String, String>() {{
put("_os", "Android");
put("_os_version", "10");
put("_app_version", "1.2");
}};

Map<String, String> location = new HashMap<String, String>() {{
put("ip_address", "192.168.1.1");
put("city", "Lahore");
put("country_code", "PK");
put("location", "31.5204,74.3587");
}};

Countly.backendMode().sessionBegin(DEVICE_ID, metrics, location, null);
break;
}
case 7: // update session
Countly.backendMode().sessionUpdate(DEVICE_ID, 10, null);
break;
case 8: // end session
Countly.backendMode().sessionEnd(DEVICE_ID, 20, null);
break;
case 9: { // record a direct request
Map<String, String> requestData = new HashMap<>();
requestData.put("device_id", "id");
requestData.put("timestamp", "1646640780130");
requestData.put("end_session", "1");
requestData.put("session_duration", "20.5");
Countly.backendMode().recordDirectRequest(DEVICE_ID, requestData, null);
break;
}
case 99: // record data with legacy call
recordDataWithLegacyCalls();
break;
default:
break;
}

}

// Gracefully stop SDK to stop all SDK threads and allow this app to exit
// Just in case, usually you don't want to clear data to reuse device id for next app runs
// and to send any requests which might not be sent
Countly.stop(false);
}
}
Loading

0 comments on commit ca61a7b

Please sign in to comment.