-
Notifications
You must be signed in to change notification settings - Fork 9
Collect and send custom attributes for capture feature #89
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
Merged
Merged
Changes from all 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 6be4756
feat(sdk): add interface for set/remove custom attributes from user
satsukies 58aa865
feat(sdk): manage custom attributes with HashMap and implement valida…
satsukies fd54751
chore(sdk): bumpup version to 4.8.0
satsukies e4a3d40
fix(sdk): add import
satsukies ce47071
fix(sdk): fix test failed
satsukies b94250d
test(sdk): add test for CustomAttributes
satsukies d8bcc73
fix(sdk): add CustomAttributes for capture feature
satsukies c5c8f3c
test(sdk): add CustomAttributesTest#toJsonString()
satsukies 9be4d92
feat(sdk): write custom attributes when collect device state event re…
satsukies 480de52
chore(sample): update sample code set custom attributes
satsukies 6b56334
fix(sdk): fix build failed due to missing some methods in sdkMock
satsukies 11d51ab
fix(sdk): don't send values when it is null
satsukies 2b8ecee
fix(sdk): don't send package name from SDK
satsukies 95dad51
fix(sdk): provide getter only
satsukies 4889e37
fix(sdk): fix too general naming of some constant values
satsukies 823463e
fix(sdk): class became final and hide constructor from outside
satsukies 71e158f
fix(sdk): simplify redundant condition
satsukies 9bcb4f1
fix(sdk): improve put operation for thread safety
satsukies 9c16ebf
fix(sdk): use Logger instead of Log
satsukies f1a9aff
test(sdk): add CustomAttributesInterfaceTest
satsukies 854288a
chore(sample): improvement sample codes
satsukies c829658
test(sdk): fix symbolic link
satsukies 1c5407d
test(sdk): fix testcase method naming
satsukies 45ac031
fix(sdk): all public method always return non-null value
satsukies 45084e1
test(sdk): add testcase checking behavior of isEmpty() and size()
satsukies 4519aa2
fix(sdk): use try-catch insert value via content resolver
satsukies 024b6cc
fix(sdk): append prefix to keys when call toJsonString()
satsukies 1627bff
fix(sdk): use synchronized when access CustomAttributes
satsukies 6f0ebd8
test(sdk): use different values, check return type
satsukies 7a510d6
fix(sdk): fix CustomAttributes class become thread-safe
satsukies 7391f7f
fix(sdk): send attributes collect by SDK
satsukies 110a00e
chore(sdk): documentation
satsukies 063fc76
test(sdk): add testcase of toJSONString()
satsukies File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
sdk/src/main/java/com/deploygate/sdk/CustomAttributes.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| package com.deploygate.sdk; | ||
|
|
||
| import com.deploygate.sdk.internal.Logger; | ||
|
|
||
| import org.json.JSONException; | ||
| import org.json.JSONObject; | ||
|
|
||
| import java.util.regex.Pattern; | ||
|
|
||
| /** | ||
| * This class provides store key-value pairs. | ||
| * These methods are thread-safe. | ||
| */ | ||
| public final class CustomAttributes { | ||
|
|
||
| private static final String TAG = "CustomAttributes"; | ||
|
|
||
| private static final int MAX_ATTRIBUTES_SIZE = 8; | ||
| private static final Pattern VALID_KEY_PATTERN = Pattern.compile("^[a-z][_a-z0-9]{2,31}$"); | ||
| private static final int MAX_VALUE_LENGTH = 64; | ||
|
|
||
| private final Object mLock; | ||
| private JSONObject attributes; | ||
|
|
||
| CustomAttributes() { | ||
| mLock = new Object(); | ||
| attributes = new JSONObject(); | ||
| } | ||
|
|
||
| /** | ||
| * Put a string value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value value must be non-null and its length must be less than 64. | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putString(String key, String value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Put an int value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value int value | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putInt(String key, int value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Put a long value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value long value | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putLong(String key, long value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Put a float value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value float value | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putFloat(String key, float value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Put a double value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value double value | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putDouble(String key, double value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Put a boolean value with the key. | ||
| * If the key already exists, the value will be overwritten. | ||
| * @param key key must be non-null and match the valid pattern. | ||
| * @param value boolean value | ||
| * @return true if the value is put successfully, otherwise false. | ||
| * @see CustomAttributes#VALID_KEY_PATTERN | ||
| */ | ||
| public boolean putBoolean(String key, boolean value) { | ||
| return putInternal(key, value); | ||
| } | ||
|
|
||
| /** | ||
| * Remove the value with the key. | ||
| * @param key name of the key to be removed. | ||
| */ | ||
| public void remove(String key) { | ||
| synchronized (mLock) { | ||
| attributes.remove(key); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Remove all key-value pairs. | ||
| */ | ||
| public void removeAll() { | ||
| synchronized (mLock) { | ||
| // recreate new object instead of removing all keys | ||
| attributes = new JSONObject(); | ||
| } | ||
| } | ||
|
|
||
| int size() { | ||
| synchronized (mLock) { | ||
| return attributes.length(); | ||
| } | ||
| } | ||
|
|
||
| String getJSONString() { | ||
| synchronized (mLock) { | ||
| return attributes.toString(); | ||
| } | ||
| } | ||
|
|
||
| private boolean putInternal(String key, Object value) { | ||
| if (!isValidKey(key)) { | ||
| return false; | ||
| } | ||
|
|
||
| if (!isValidValue(value)) { | ||
| return false; | ||
| } | ||
|
|
||
| synchronized (mLock) { | ||
| try { | ||
| attributes.put(key, value); | ||
|
|
||
| if (attributes.length() > MAX_ATTRIBUTES_SIZE) { | ||
| // rollback put operation | ||
| attributes.remove(key); | ||
| Logger.w(TAG, "Attributes already reached max size. Ignored: " + key); | ||
| return false; | ||
| } | ||
| } catch (JSONException e) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
| Logger.w(TAG, "Failed to put attribute: " + key, e); | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| private boolean isValidKey(String key) { | ||
| if (key == null || key.equals("true") || key.equals("false") || key.equals("null")) { | ||
| Logger.w(TAG, "Not allowed key: " + key); | ||
| return false; | ||
| } | ||
|
|
||
| if (!VALID_KEY_PATTERN.matcher(key).matches()) { | ||
| Logger.w(TAG, "Invalid key: " + key); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| private boolean isValidValue(Object value) { | ||
| if (value == null) { | ||
| Logger.w(TAG, "Value is null"); | ||
| return false; | ||
| } | ||
|
|
||
| if (value instanceof String && ((String) value).length() > MAX_VALUE_LENGTH) { | ||
| Logger.w(TAG, "Value too long: " + value); | ||
| return false; | ||
| } else if (value instanceof String || value instanceof Number || value instanceof Boolean) { | ||
| return true; | ||
| } else { | ||
| // dead code | ||
| Logger.w(TAG, "Invalid value: " + value); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.