Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collect and send custom attributes for capture feature #89

Merged
merged 34 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
80d1bc1
chore(sdk): add constant values for collect custom attributes
satsukies Jul 22, 2024
6be4756
feat(sdk): add interface for set/remove custom attributes from user
satsukies Jul 22, 2024
58aa865
feat(sdk): manage custom attributes with HashMap and implement valida…
satsukies Jul 22, 2024
fd54751
chore(sdk): bumpup version to 4.8.0
satsukies Jul 22, 2024
e4a3d40
fix(sdk): add import
satsukies Jul 22, 2024
ce47071
fix(sdk): fix test failed
satsukies Jul 22, 2024
b94250d
test(sdk): add test for CustomAttributes
satsukies Jul 22, 2024
d8bcc73
fix(sdk): add CustomAttributes for capture feature
satsukies Jul 22, 2024
c5c8f3c
test(sdk): add CustomAttributesTest#toJsonString()
satsukies Jul 22, 2024
9be4d92
feat(sdk): write custom attributes when collect device state event re…
satsukies Jul 22, 2024
480de52
chore(sample): update sample code set custom attributes
satsukies Jul 22, 2024
6b56334
fix(sdk): fix build failed due to missing some methods in sdkMock
satsukies Jul 22, 2024
11d51ab
fix(sdk): don't send values when it is null
satsukies Jul 22, 2024
2b8ecee
fix(sdk): don't send package name from SDK
satsukies Jul 22, 2024
95dad51
fix(sdk): provide getter only
satsukies Jul 22, 2024
4889e37
fix(sdk): fix too general naming of some constant values
satsukies Jul 22, 2024
823463e
fix(sdk): class became final and hide constructor from outside
satsukies Jul 22, 2024
71e158f
fix(sdk): simplify redundant condition
satsukies Jul 22, 2024
9bcb4f1
fix(sdk): improve put operation for thread safety
satsukies Jul 22, 2024
9c16ebf
fix(sdk): use Logger instead of Log
satsukies Jul 22, 2024
f1a9aff
test(sdk): add CustomAttributesInterfaceTest
satsukies Jul 22, 2024
854288a
chore(sample): improvement sample codes
satsukies Jul 22, 2024
c829658
test(sdk): fix symbolic link
satsukies Jul 23, 2024
1c5407d
test(sdk): fix testcase method naming
satsukies Jul 23, 2024
45ac031
fix(sdk): all public method always return non-null value
satsukies Jul 23, 2024
45084e1
test(sdk): add testcase checking behavior of isEmpty() and size()
satsukies Jul 23, 2024
4519aa2
fix(sdk): use try-catch insert value via content resolver
satsukies Jul 23, 2024
024b6cc
fix(sdk): append prefix to keys when call toJsonString()
satsukies Jul 23, 2024
1627bff
fix(sdk): use synchronized when access CustomAttributes
satsukies Jul 23, 2024
6f0ebd8
test(sdk): use different values, check return type
satsukies Jul 24, 2024
7a510d6
fix(sdk): fix CustomAttributes class become thread-safe
satsukies Jul 24, 2024
7391f7f
fix(sdk): send attributes collect by SDK
satsukies Jul 24, 2024
110a00e
chore(sdk): documentation
satsukies Jul 24, 2024
063fc76
test(sdk): add testcase of toJSONString()
satsukies Jul 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ abstract class BaseSdkPlugin : Plugin<Project> {
/**
* sdk/java/com/deploygate/sdk/HostAppTest.java needs to be changed for a new release
*/
const val ARTIFACT_VERSION = "4.7.1"
const val ARTIFACT_VERSION = "4.8.0"

val JAVA_VERSION = JavaVersion.VERSION_1_7
}
Expand Down
199 changes: 199 additions & 0 deletions sdk/src/main/java/com/deploygate/sdk/DeployGate.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ public class DeployGate {
private static final String DEPLOYGATE_PACKAGE = "com.deploygate";
private static final Object sPendingEventLock = new Object();

private static final int MAX_BUILD_ENVIRONMENTS_SIZE = 8;
private static final int MAX_RUNTIME_EXTRAS_SIZE = 8;
private static final Pattern USER_INPUT_KEY_PATTERN = Pattern.compile("^[a-z][_a-z0-9]{2,31}$");
private static final int MIN_USER_INPUT_KEY_LENGTH = 3;
private static final int MAX_USER_INPUT_KEY_LENGTH = 32;
private static final int MAX_USER_INPUT_VALUE_LENGTH = 64;

private static DeployGate sInstance;

private final Context mApplicationContext;
Expand All @@ -59,6 +66,8 @@ public class DeployGate {
private final CustomLogInstructionSerializer mCustomLogInstructionSerializer;
private final HashSet<DeployGateCallback> mCallbacks;
private final HashMap<String, Bundle> mPendingEvents;
private final HashMap<String, Object> mBuildEnvironments;
private final HashMap<String, Object> mRuntimeExtras;
private final String mExpectedAuthor;
private String mAuthor;

Expand Down Expand Up @@ -279,6 +288,8 @@ private DeployGate(
mCustomLogInstructionSerializer = new CustomLogInstructionSerializer(mHostApp.packageName, sdkConfiguration.customLogConfiguration);
mCallbacks = new HashSet<>();
mPendingEvents = new HashMap<>();
mBuildEnvironments = new HashMap<>();
mRuntimeExtras = new HashMap<>();
mExpectedAuthor = sdkConfiguration.appOwnerName;

prepareBroadcastReceiver();
Expand Down Expand Up @@ -1390,4 +1401,192 @@ public static String getDistributionUserName() {

return sInstance.mDistributionUserName;
}

public static boolean putBuildEnvironmentValue(String key, String value) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add comments each public method.

if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static boolean putBuildEnvironmentValue(String key, int value) {
if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static boolean putBuildEnvironmentValue(String key, long value) {
if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static boolean putBuildEnvironmentValue(String key, float value) {
if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static boolean putBuildEnvironmentValue(String key, double value) {
if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static boolean putBuildEnvironmentValue(String key, boolean value) {
if (sInstance != null) {
return sInstance.putBuildEnvironmentValueInternal(key, value);
}
return false;
}

public static void removeBuildEnvironmentValue(String key) {
if (sInstance != null) {
sInstance.removeBuildEnvironmentValueInternal(key);
}
}

public static void removeAllBuildEnvironmentValues() {
if (sInstance != null) {
sInstance.removeAllBuildEnvironmentValuesInternal();
}
}

public static boolean putRuntimeExtraValue(String key, String value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static boolean putRuntimeExtraValue(String key, int value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static boolean putRuntimeExtraValue(String key, long value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static boolean putRuntimeExtraValue(String key, float value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static boolean putRuntimeExtraValue(String key, double value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static boolean putRuntimeExtraValue(String key, boolean value) {
if (sInstance != null) {
return sInstance.putRuntimeExtraValueInternal(key, value);
}
return false;
}

public static void removeRuntimeExtraValue(String key) {
if (sInstance != null) {
sInstance.removeRuntimeExtraValueInternal(key);
}
}

public static void removeAllRuntimeExtraValues() {
if (sInstance != null) {
sInstance.removeAllRuntimeExtraValuesInternal();
}
}

private boolean putBuildEnvironmentValueInternal(String key, Object value) {
if (mBuildEnvironments.size() >= MAX_BUILD_ENVIRONMENTS_SIZE && !mBuildEnvironments.containsKey(key)) {
Log.w(TAG, "BuildEnvironment already full. Ignored: " + key);
return false;
}

if (!isValidKey(key)) {
return false;
}

if (!isValidValue(value)) {
return false;
}

mBuildEnvironments.put(key, value);
return true;
}

private void removeBuildEnvironmentValueInternal(String key) {
mBuildEnvironments.remove(key);
}

private void removeAllBuildEnvironmentValuesInternal() {
mBuildEnvironments.clear();
}

private boolean putRuntimeExtraValueInternal(String key, Object value) {
if (mRuntimeExtras.size() >= MAX_RUNTIME_EXTRAS_SIZE && !mRuntimeExtras.containsKey(key)) {
Log.w(TAG, "RuntimeExtra already full. Ignored: " + key);
return false;
}

if (!isValidKey(key)) {
return false;
}

if (!isValidValue(value)) {
return false;
}

mRuntimeExtras.put(key, value);
return true;
}

private void removeRuntimeExtraValueInternal(String key) {
mRuntimeExtras.remove(key);
}

private void removeAllRuntimeExtraValuesInternal() {
mRuntimeExtras.clear();
}

private boolean isValidKey(String key) {
if (key == null || key.equals("true") || key.equals("false") || key.equals("null")) {
Log.w(TAG, "Not allowed key: " + key);
return false;
}

if (key.length() < MIN_USER_INPUT_KEY_LENGTH || key.length() > MAX_USER_INPUT_KEY_LENGTH || !USER_INPUT_KEY_PATTERN.matcher(key).matches()) {
Log.w(TAG, "Invalid key: " + key);
return false;
}

return true;
}

private boolean isValidValue(Object value) {
if (value == null) {
Log.w(TAG, "Value is null");
return false;
}

if (value instanceof String && ((String) value).length() > MAX_USER_INPUT_VALUE_LENGTH) {
Log.w(TAG, "Value too long: " + value);
return false;
}

return true;
}
}
31 changes: 31 additions & 0 deletions sdk/src/main/java/com/deploygate/service/DeployGateEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public interface DeployGateEvent {
// namespace:
// ACTION => a
// EXTRA => e
// KEY => k
//
// content:
// should be hyphen-separated string and be lower cases
Expand All @@ -27,6 +28,11 @@ public interface DeployGateEvent {
public static final String ACTION_COMPOSE_COMMENT = "composeComment";
public static final String ACTION_VISIBILITY_EVENT = "a.visibility-event";

/**
* @since 4.8.0
*/
public static final String ACTION_COLLECT_DEVICE_STATES = "a.collect-device-states";

public static final String EXTRA_AUTHOR = "author";
public static final String EXTRA_EXPECTED_AUTHOR = "expectedAuthor";

Expand Down Expand Up @@ -121,6 +127,31 @@ public interface DeployGateEvent {
*/
public static final String EXTRA_VISIBILITY_EVENT_ELAPSED_REAL_TIME_IN_NANOS = "e.visibility-event-elapsed-real-time";

/**
* @since 4.8.0
*/
public static final String EXTRA_TARGET_URI_FOR_REPORT_DEVICE_STATES = "e.target-uri-for-report-device-states";

/**
* @since 4.8.0
*/
public static final String KEY_BUILD_ENVIRONMENT = "k.build-environment";

/**
* @since 4.8.0
*/
public static final String KEY_RUNTIME_EXTRAS = "k.runtime-extras";

/**
* @since 4.8.0
*/
public static final String KEY_PACKAGE_NAME = "k.package-name";

/**
* @since 4.8.0
*/
public static final String KEY_EVENT_AT = "k.event-at";

interface VisibilityType {
int BACKGROUND = 0;
int FOREGROUND = 1;
Expand Down
Loading
Loading